本文根据《大话数据结构》一书,实现了Java版的堆排序。html
更多:数据结构与算法合集java
堆排序种的堆指的是数据结构中的堆,而不是内存模型中的堆。算法
堆:能够当作一棵彻底二叉树,每一个结点的值都大于等于(小于等于)其左右孩子结点的值,称为大顶堆(小顶堆)。数据结构
大顶堆(左)与小顶堆(右)ide
堆排序的基本思想:将带排序的序列构形成大顶堆,最大值为根结点。将根结点与最后一个元素交换,对除最大值外的剩下n-1个元素从新构形成大顶堆,能够得到次大的元素。反复执行,就能够获得一个有序序列了。函数
构造大顶堆的方法:post
1.首先复习彻底二叉树的性质,层序遍历,当第一个元素索引从0开始时,索引为i的左孩子的索引是 (2*i+1),右孩子的索引是 (2*i+2)。测试
2.设计一个函数heapAdjust(),对于一个序列(除了第一个根结点外,其他结点均知足最大堆的定义),经过这个函数能够将序列调整为正确的大顶堆。url
3.正式构造:将带排序的序列当作一棵彻底二叉树的层序遍历,咱们从下往上,从右往左,依次将每一个非叶子结点看成根结点,使用heapAdjust()调整成大顶堆。spa
具体细节的实现参阅代码,比较清楚,再也不赘述。
(含测试代码)
/** * * @Description 堆排序 * * @author yongh * */ public class HeapSort { public void heapSort(int[] arr) { if(arr==null || arr.length<=0) return; int len=arr.length; for(int i=len/2-1;i>=0;i--) { //从最后一个父结点开始构建最大堆 heapAdjust(arr,i,len-1); } for(int i=len-1;i>=0;i--) { int temp=arr[0]; arr[0]=arr[i]; arr[i]=temp; heapAdjust(arr, 0, i-1); } } /* * 功能:调整堆为最大堆 * [i……j]中,除了i以外,部分子树都知足最大堆定义 */ private void heapAdjust(int[] arr, int start, int end) { int temp=arr[start]; int child=2*start+1; while(child<=end) { if(child+1<=end && arr[child+1]>arr[child]) //记得child+1<=end的判断 child++; //较大的孩子 if(arr[child]<=temp) break; arr[start]=arr[child]; start=child; child=child*2+1; } arr[start]=temp; } // =========测试代码======= public void test1() { int[] a = null; heapSort(a); System.out.println(Arrays.toString(a)); } public void test2() { int[] a = {}; heapSort(a); System.out.println(Arrays.toString(a)); } public void test3() { int[] a = { 1 }; heapSort(a); System.out.println(Arrays.toString(a)); } public void test4() { int[] a = { 3, 3, 3, 3, 3 }; heapSort(a); System.out.println(Arrays.toString(a)); } public void test5() { int[] a = { -3, 6, 3, 1, 3, 7, 5, 6, 2 }; heapSort(a); System.out.println(Arrays.toString(a)); } public static void main(String[] args) { HeapSort demo = new HeapSort(); demo.test1(); demo.test2(); demo.test3(); demo.test4(); demo.test5(); } }
null [] [1] [3, 3, 3, 3, 3] [-3, 1, 2, 3, 3, 5, 6, 6, 7]
构建堆的时间复杂度为O(n);每次调整堆的时间为O(logn),共要调整n-1次,因此重建堆的时间复杂度为O(nlogn)。
所以整体来讲,堆排序的复杂度为O(nlogn)。不过因为记录的比较和交换是跳跃式进行的,所以堆排序是不稳定的排序方法。
更多:数据结构与算法合集