java面试算法之堆排序

/**
 * 堆排序
 * 堆的概念:一个无序序列,{k1,k2,k3,k4,k5,k6,k7.......kn},
 * 当(ki<k(2i+1)&&ki<k(2i+2)) || (ki>k(2i+1) && ki>k(2i+2)))
 * 第一步:先初始化堆,怎样初始化堆呢?循环完全二叉树中的第(n/2-1)个节点
 * (为啥从这个节点开始呢?因为二叉树排序应该从最下边开始往上边冒,而
 * (n/2-1)是最后一个非叶子节点),那么循环多少次呢?循环n/2次。
 * (这里初始化堆就只需要初始化第0个和第j个了,因为其他元素都输出了)
 * Created by wuxiaojun on 2017/12/15.
 */

public class HeapSort {

    public static void main(String[] args) {
        int[] arrays = {99, 88, 101, 2, 9, 6, 22, 0, 123, 987, 6, 8, 19};
        int length = arrays.length;
        // 初始化堆
        for (int i = length / 2; i >= 0; i--) {
            sift(i, length, arrays);
        }
        // 将堆的最后一个元素和第0个元素进行调换并输出
        for (int j = length - 1; j > 0; j--) {
            int temp = arrays[0];
            arrays[0] = arrays[j];
            arrays[j] = temp;
            sift(0, j, arrays); // 为什么是0和j呢?因为每次把第0个元素和最后一个元素进行互换了之后,需要重新初始化堆,但是这次初始化堆,只需要比较互换后的第0个比较它的孩子就好。
        }
        forEach(arrays);
    }

    /***
     * 初始化堆
     * @param low
     * @param high
     */
    public static void sift(int low, int high, int[] arrays) {
        int i = low;
        int j = 2 * i + 1;
        int temp = arrays[i];
        while (j < high) {
            if (j < high - 1 && arrays[j + 1] > arrays[j]) {
                j++; // 拿到左右孩子最小的一个的索引
            }
            if (temp < arrays[j]) { // 如果父亲的值小于孩子中最大的一个的值,则需要进行互换
                arrays[i] = arrays[j]; // arrays[i] = arrays[j] = 95;
                i = j; // i = j = 5;
                j = 2 * i + 1; // j = 11;
            } else {
                j = high + 1; // 退出循环
            }
        }
        arrays[i] = temp; // 这里为啥要把temp的值赋给arrays[i]呢?因为当temp < arrays[j]的时候,把j的索引赋给了i,所以i变成了j,这里理解其实就是j,但是执行44-46行代码之后把j的值重新计算了,所以就用i
    }

    public static void forEach(int[] arrgs) {
        for (int j = 0; j < arrgs.length; j++) {
            System.out.print(arrgs[j] + "  ");
        }
        System.out.println("遍历完成");
    }

}

猜你喜欢

转载自blog.csdn.net/u010648159/article/details/78888134
今日推荐