堆排序

作者: 不服输的小蜗牛 | 来源:发表于2020-06-27 18:39 被阅读0次

什么是堆排序?
就是通过不断取出最大堆的堆顶元素。取完之后剩下的数据排序满足最大堆之后再次取堆顶元素,重复以上操作最终实现一个又大到小的排序。

我们以数组 int[] arr = {50, 23,22,1,70,24,34,45}为例:
首先我们要让数组满足我们的最大二叉堆的性质,也就是所有的父亲节点都大于等于其子节点。我们通过Heapify来实现,也就是找到最后一个元素的父亲节点,然后从倒数第一个元素的父亲节点递减的执行siftDown操作,完成二叉堆。
siftDown:就是不断和自己的子孩子进行比较,直到大于等于自己的最大子孩子。

第一轮siftDown之后,以上数组变成 {70,50,34,45,23,24,22,1},然后我们让角标0和角标arr.leng-1进行交换,变成了{1,50,34,45,23,24,22,70}

第二轮执行siftDown之后,{50,45,34,1,23,24,22,70},我们让角标0和角标arr.leng-2进行交换。变成了{22,45,34,1,23,24,50,70}

第三轮执行siftDown之后,{45,23,34,1,22,22,50,70},然后我们让角标0和角标arr.leng-3 进行交换,变成了{24,23,34,1,22,45,50,70}

第四轮执行siftDown之后,.......变成了{22,23,24,1,34,45,50,70}
第五轮执行siftDown之后,.......变成了{22,23,1,24,34,45,50,70}
第六轮执行siftDown之后,.......变成了{22,1,23,24,34,45,50,70}
第七轮执行siftDown之后,.......变成了{1,22,23,24,34,45,50,70}

八个元素执行了七轮循环 也就是arr.leng-1次循环

代码实现如下


    public static  void heapSort(int[] arr) {

        for (int i = 0; i < arr.length-1; i++) {
            //从最后一个角标的父亲节点开始重复向上执行,siftDown的操作。
            // 由于每次执行完之后最大值在最后一个角标,所以我们要获取 arr.length-i-1的父亲节点
            for (int j = getParent(arr.length - 1-i); j >= 0; j--) {
                siftDown(arr, j, arr.length - i);
            }
            //执行完下浮操作之后,交换角标0 和arr.length-i-1角标交换。
            int temp = arr[0];
            arr[0] = arr[arr.length-i-1];
            arr[arr.length-i-1] = temp;
        }


    }

    /**、
     * 获取index的左孩子角标
     * @param index
     * @return
     */
    private static int getLeftChild(int index) {
        return index * 2 + 1;
    }

    /**
     * 获取index的父亲角标
     * @param index
     * @return
     */
    private static int getParent(int index) {
        if (index == 0) {
            throw new IllegalArgumentException("zero no parent ");
        }
        return (index - 1) / 2;
    }

    /**
     * 获取index的又孩子角标
     * @param index
     * @return
     */
    private static int getRightChild(int index) {
        return index * 2 + 2;
    }

    /**
     *
     * @param array 需要排序的数组
     * @param k endIndex的父亲节点,
     * @param endIndex
     */
    private static void siftDown(int[] array, int k, int endIndex) {

        //如果k角标的左孩子角标没有超过endindex,就继续执行
        while (getLeftChild(k) < endIndex) {
            
            //获取最孩子的角标
            int j = getLeftChild(k);
            //如果j+1<endIndex,表示k有右孩子,如果右孩子大于左孩子,我们要把较大的元素的角标赋值给j
            if (j + 1 < endIndex && array[j + 1]-(array[j]) > 0) {
                j = getRightChild(k);

            }
            //如果角标k的元素大于孩子中最大的值,循环结束,如果小于最大值,则k和j角标交换元素,然后吧j赋值给k,执行下次循环
            if (array[k]-(array[j]) >= 0) {
                break;
            }
            int temp = array[k];
            array[k] = array[j];
            array[j] = temp;
            k = j;
        }
    }


相关文章

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 堆和堆排序

    最小K个数 堆排序 堆排序

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • iOS算法总结-堆排序

    iOS算法总结-堆排序 iOS算法总结-堆排序

  • 堆排序

    转载:图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选...

  • 排序

    原创 堆排序: 使用visit数组从本质出发获取大顶堆排序。

  • 堆排序

    堆排序

  • C++基础入门之模板堆排序(上):模板上的list的创造与操作

    整段源码链接C++的模板元堆排序 要点 组建数据结构list 组建对list的各种基本操作 堆排序中组建堆排序个个...

  • 3.2-选择排序-堆排序

    参考链接 选择排序:堆排序(Heap Sort) 白话经典算法系列之七 堆与堆排序 堆排序与快速排序,归并排序一样...

网友评论

      本文标题:堆排序

      本文链接:https://www.haomeiwen.com/subject/dawmxktx.html