一、概念
堆排序是简单选择排序的一种改进,改进的着眼点是:如何减少关键码的比较次数。
简单选择排序在一趟排序中仅选出最小关键码,没有把一趟比较结果保存下来,因而记录的比较次数较多。
堆排序在选出最小关键码的同时,也找出较小关键码,减少了在后面的选择中的比较次数,从而提高了整个排序的效率。
堆是具有下列性质的完全二叉树:
每个结点的值都小于或者等于其左右孩子结点的值(称为小根堆);
或者每个结点的值都大于或等于其左右孩子结点的值(称为大根堆);
堆排序对原始记录的排列状态并不敏感,相对于快速排序,这是堆排序最大的优点。
二、复杂度
排序方法 | 最差时间分析 | 最好时间分析 | 平均时间复杂度 | 空间复杂度 | 稳定性 |
堆排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不稳定 |
三、代码实现
1 package sort; 2 3 public class HeapSort { 4 public static void main(String[] args) { 5 HeapSort heapSort = new HeapSort(); 6 //int[] array = {11,7,6,1,8,4,3,2,5}; 7 int[] array = {12,2,3,4,8,6,7,15}; 8 array = heapSort.heapSort(array); 9 for(int i: array){ 10 System.out.print(i + " "); 11 } 12 } 13 14 //堆排序 15 public int[] heapSort(int[] array){ 16 //初始化堆,array[0]为第一趟值最大的元素 17 for(int i = (array.length-2)/2;i>=0;i--) 18 adjustDownToUp(array, i, array.length); 19 //进行排序 20 for(int i= array.length-1; i > 0; i--){ 21 int temp=array[0]; 22 array[0] = array[i]; 23 array[i] = temp;//交换值 24 //然后将剩下的无序元素继续调整为大根堆 25 adjustDownToUp(array, 0, i); 26 } 27 return array; 28 } 29 //将元素array[k]自下向上逐步调整树形结构,数组下标从0开始 30 private void adjustDownToUp(int[] array, int k, int length){ 31 int temp = array[k]; 32 for(int i = 2*k + 1; i < length; i = 2*i+1){//i初始化为节点k的左孩子 33 //比较k的左右孩子节点,选择较大的节点 34 if(i+1 < length && array[i] < array[i+1]){//如果k的右孩子>左孩子,则i指向右孩子 35 i++; 36 } 37 if(temp >= array[i]){ 38 //如果根节点大于等于左右孩子的较大者,则本次调整结束 39 break; 40 }else{ 41 array[k] = array[i];//将左右节点中较大值赋值给k 42 k = i;//修改k值(关键),以便继续向下调整 43 } 44 } 45 array[k] = temp; 46 } 47 }