1. 堆排序概述
- 堆排序 Heap Sort是对简单选择排序的优化:选择排序是在待排序的 i i i个中选择最小(或最大)的数,交换到数组前面来,每次都需要比较 i − 1 i-1 i−1次,如果在确保每次都能够选择最小(或最大)数的同时,对每次比较结果进行调整,那么排序的效率会有更大的提升,堆排序正是做这样的事情。
- 堆排序算法是Floyd和Williams在1964年共同发明的,同时,他们发明了“堆”这样的数据结构:
- 堆:堆是某一节点都小于(或都大于)左右子树的完全二叉树。
- 堆排序的最坏、最好、平均时间复杂度均为 O ( n l o g n ) O(nlogn) O(nlogn),也是不稳定排序
- 堆的分类
- 大顶堆:节点大于左右子树
- 小顶堆:节点小于左右子树
如果按照层序遍历的方式给节点从1开始编号,则节点之间满足如下关系:
如果堆是数组顺序存储的:
2. 堆排序思想
- 堆排序的基本思想如下(以升序为例):
- 步骤一:将待排序的数组构造成一个大顶堆,此时数组的最大值就是大顶堆的根节点
- 步骤二:将根节点和末尾元素进行交换,此时末尾元素就是最大值
- 步骤三:去掉此末尾元素(已排序好),将 n − 1 n-1 n−1个元素重新按步骤一排序
- 按以上如此反复执行,就能够得到升序的数组了
3. 图解堆排序
假设有一个数组 { 4 , 6 , 8 , 5 , 9 } \{4, 6, 8, 5, 9\} {
4,6,8,5,9},要求使用堆排序法,将数组升序排序
步骤一:构造初始堆,按要求将给定无序数组构造成一个大顶堆。
- 初始无序数组结构如下:
- 此时我们从最后一个非叶子节点开始(我们的目标是大顶堆的根节点,非叶子节点自然不用调整),最后一个非叶子节点的计算公式是 a r r . l e n g t h 2 − 1 \frac{arr.length}{2}-1 2arr.length−1,我们从左至右,从下至上进行调整。
堆是一颗完全二叉树,设某堆总共有n个节点,则最后一个非叶子节点的计算公式如下: