基本概念:
二叉堆是完全二叉树或者是近似完全二叉树。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。
当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。
一般将二叉堆简称为堆。
基本思想:
1.把n个元素建立最大堆,把堆顶元素A[0]与待排序序列的最后一个数据A[n-1]交换;
2.把剩下的n-1个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-2]交换;
3.把剩下的n-2个元素重新建立最大堆,把堆顶元素A[0]与待排序序列的最后一个元素A[n-3]交换;
重复以上步骤,直到把最后两个元素建成最大堆并进行交换,得到的序列就是排序后的有序序列。
堆排序是不稳定的排序算法,时间复杂度为:O(NlogN).
Java实现:
package sort; public class HeapSort{ public static void main(String[] args) { new HeapSort().run(); } public void run(){ int [] a={17,8,45,84,2,94}; int len=a.length; /** * 循环建堆 */ for(int i=0;i<len-1;i++){ /** * 建堆,建一次最大堆,寻到一个待排序序列的最大数 */ buildMaxHeap(a,len-1-i); /** * 交换堆顶(待排序序列最大数)和最后一个元素 */ swap(a,0,len-1-i); } for(int j=0;j<len;j++){ System.out.print(a[j]+" "); } } /** * 对数组 从0到lastIndex建大顶堆 */ public void buildMaxHeap(int[] arr, int lastIndex){ /** * 从最后一个节点(lastIndex)的父节点开始 */ for(int i=(lastIndex-1)/2;i>=0;i--){ /** * k保存正在判断的节点 */ int k=i; /** * 如果当前k节点的子节点存在 */ while(k*2+1<=lastIndex){ /** * k节点的左子节点的索引 */ int biggerIndex=2*k+1; /** * 如果k节点的左子节点biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在 */ if(biggerIndex<lastIndex){ /** * 若果右子节点的值较大 */ if(arr[biggerIndex]<arr[biggerIndex+1]){ /** * biggerIndex总是记录较大子节点的索引 */ biggerIndex++; } } /** * 如果k节点的值小于其较大的子节点的值 ,交换他们 */ if(arr[k]<arr[biggerIndex]){ swap(arr,k,biggerIndex); /** * 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值 */ k=biggerIndex; }else{ /** * 当前判断结点k(父结点),大于他的两个子节点时,跳出while循环 */ break; } } } } /** * 交换下标为i、j的两个元素 */ private void swap(int[] data, int i, int j) { int tmp=data[i]; data[i]=data[j]; data[j]=tmp; } }
结果展示:
(本文仅供学习交流,如有更好的思路,欢迎留下意见供大家探讨学习~)