Java八大排序之堆排序
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
根据根结点是否是最大值还是最小值和子结点的键值是否小于还是大于它的父结点可分为两种堆,如下:
1.大顶堆:每个结点的键值都小于它的父结点;
2.小顶堆:每个结点的键值都大于它的父节点;
堆排序基本思想:
1.将数组排列成大顶堆(或小顶堆);
2.把根结点和尾结点交换,然后把n-1个元素重新构成一个大顶堆(或小顶堆);
3.重复第2步,直到最后一个元素。
流程图(为了不太麻烦,所以就减少些数据):
一,先将数组排序成大顶堆
二,把根结点和末尾结点交换
代码:
1 /** 2 * 堆排序 3 */ 4 public class TestHeap { 5 //创建大顶堆 6 public static void maximumHeap(int k, int[] arr,int m) { 7 int i, j, temp; 8 boolean finished; 9 i = k; 10 j = 2*i+1; 11 temp = arr[k]; 12 finished = false; 13 while((j <= m) && !finished){ 14 //孩子结点位置小于数组长度 且 右孩子大于左孩子 15 if ((j < m) && (arr[j+1] > arr[j])){ 16 j++; //把右孩子结点当作最大孩子结点 17 } 18 //如果最大的孩子结点小于其根节点 19 if (temp >= arr[j]){ 20 finished = true; //结束循环 21 }else{ 22 //把最大子节点赋给根结点 23 arr[i] = arr[j]; 24 i = j; 25 //循环下一个根结点 26 j = 2*j+1; 27 } 28 } 29 arr[i] = temp; 30 } 31 32 //交换 33 public static void heapsort(int[] arrays) { 34 int i; 35 //从最后一个非叶节点开始构建大顶堆 36 for (i = arrays.length / 2 - 1; i >= 0; i--) { 37 maximumHeap(i, arrays, arrays.length); 38 } 39 System.out.println("建堆后:" + Arrays.toString(arrays)); 40 //从最小的叶子节点开始与根节点进行交换并重新构建大顶堆 41 for (i = arrays.length - 1; i >= 1; i--) { 42 int temp = arrays[i]; 43 arrays[i] = arrays[0]; 44 arrays[0] = temp; 45 maximumHeap(0, arrays,i-1); 46 } 47 System.out.println(Arrays.toString(arrays)); 48 } 49 50 public static void main(String[] args) { 51 int[] arrays = {49, 38, 65, 97, 176, 213, 227, 49, 78, 34, 12, 164, 11, 18, 1}; 52 heapsort(arrays); 53 } 54 }
测试结果:
建堆后:[227, 176, 213, 97, 38, 164, 65, 49, 78, 34, 12, 49, 11, 18, 1] [1, 11, 12, 18, 34, 38, 49, 49, 65, 78, 97, 164, 176, 213, 227]
时间复杂度:堆排序方法对记录数n较大的文件排序是很好的,但当n较小时,不提倡使用,因为初始建堆和调整建新堆时要进行反复的筛选。堆排序时间复杂度为O(nlog2n)。
堆排序只需存放一个记录的附加空间。
堆排序是一种不稳定的排序算法。
结语:堆排序是为了即要保存中间比较结果,减少后面的比较次数,又不占用大量的附加存储空间,使排序算法具有较好的性能才被Willioms和Floyd在1964年提出的。