堆结构、大根堆、堆操作、高级排序算法——堆排序

堆结构的概念:堆就是一个数组,它可以以完全二叉树的形式表现出来。

大根堆:完全二叉树中每棵子树的最大值都在顶部就是大根堆

如何实现大根堆?堆操作之heapInsert

heapInsert方法来实现将数组“上浮”调整成大根堆。

public static void heapInsert(int[] arr, int index) {
        //如果比父节点大,交换位置
        while (arr[index] > arr[(index - 1) / 2]) {
            swap(arr, index, (index - 1) / 2);
            //继续跟父节点比较
            index = (index - 1) / 2;
        }
    }
View Code

 

如何实现popMax操作?(找到最大值并返回,最后删掉)

堆操作之heapify方法:将一个数组调整成大根堆

用于堆排序中,将第0个位置元素和最后一个位置元素交换位置后,再将数组调整成大根堆(“下沉”操作)。

/**
     * 方法结束后,把数组变成了新的大根堆
     * <p>
     * 某个数处在index位置,看看能否往下沉
     * 不断的和左右两个孩子进行比较
     * 较大的孩子如果大于当前的父,较大孩子上来,父节点下沉。
     *
     * @param arr:数组
     * @param index:某个数处在index位置
     * @param heapSize:堆的有效长度(数组的有效长度)
     */
    public static void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;       //父节点的左孩子的下标
        while (left < heapSize) {        //左孩子小于有效长度 -> 不越界  循环结束条件:左孩子超过有效长度
            //largest:代表两个孩子中较大的那一个。
            //判断条件:left + 1 代表右孩子,如果右孩子不越界,并且右孩子大于左孩子,要右孩子,否则要左孩子.
            int largest =
                    left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;

            //此时找到两个孩子中较大的一个,与父节点进行比较。谁的值大,把下标给largest
            largest = arr[largest] > arr[index] ? largest : index;

            //如果较大孩子下标 等于 父节点下标 说明不用向下沉了,结束循环
            if (largest == index) {
                break;
            }

            //如果较大孩子的值 大于 父节点值 交换值
            swap(arr, largest, index);
            index = largest;        //把largest的下标给index
            left = index * 2 + 1;    //继续比较
        }
    }
View Code

通过heapInsert和heapify就可以很容易实现堆排序

堆排序操作:将第0个元素和最后一个元素交换,然后将堆的有效长度减1后可以得到之前0位置的元素(最大或最小的),再执行heapify操作 (下沉),重新调整堆结构。

public static void heapSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }

        //如果用户是一个一个的输入元素,就要使用heapInsert()方法来添加元素
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, i);
        }

        //如果用户一次性给了全部元素,只是用heapify方法,将全部元素(数组)构造成一个大根堆即可
        //从最后一个节点开始加入
//        for (int i = arr.length - 1; i >= 0; i--){
//            heapify(arr,i,arr.length);
//        }

        //如何排序 ? : 将0号位置元素与最后位置元素交换,将有效长度减1 得到最后位置的元素。再变成大根堆,重复此过程
        int heapSize = arr.length;
        swap(arr, 0, --heapSize);
        while (heapSize > 0) {
            heapify(arr, 0, heapSize);
            swap(arr, 0, --heapSize);
        }
    }

添加对数器后的测试结果:

posted @ 2020-07-12 23:15  硬盘红了  阅读(405)  评论(0编辑  收藏  举报