堆排序(Heapsort)堆积树设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。
排序图如下:(gif来自维基百科)
堆排序的过程就是首先构建大根堆,然后对顶元素(及最大元素)与最后个元素替换位置,heapsize减一,重新调整堆变成大根堆。重复上面操作直到heapsize等于一的时候。排序完成。
最大堆的特性:
1.某个节点的值最多和其父节点的值一样大;
2.堆中的最大元素存放在根节点中;3.在以某一个节点为根的子树中,各节点的值都不大于该子树根节点的值。
看下面图的例子:
无非是建堆判断交换。
下面以java代码的实现举例:
public class HeapSort {
public static void heapSort(int[] array){
buildHeap(array);
int n = array.length;
int i=0;
//取出该最大堆的根节点,同时,取最末尾的叶子节点来作为根节点,从此根节点开始调整堆,使其满足最大堆的特性
//直到堆的大小由n个元素降到2个
for(i=n-1;i>=1;i--){
swap(array,0,i);
heapify(array,0,i);
for (int j = 0; j < array.length; j++) {
System.out.print(array[j]);
System.out.print(",");
}
System.out.println();
}
}
//构建堆
public static void buildHeap(int[] array){
for(int i=array.length/2-1;i>=0;i--){
heapify(array,i,array.length);
}
}
//调整堆
public static void heapify(int[] data,int parentNode,int heapSize){
int leftChild = 2*parentNode+1;// 左子树的下标
int rightChild =2*parentNode+2;// 右子树的下标(如果存在的话)
int largest = 0;
//寻找3个节点中最大值节点的下标
if(leftChild<heapSize && data[leftChild]>data[parentNode]){
largest = leftChild;
}else if(rightChild<heapSize && data[rightChild]>data[largest]){
largest = rightChild;
}else{
largest = parentNode;
}
//如果最大值不是父节点,那么交换,并继续调整堆
if(largest!=parentNode){
swap(data,largest,parentNode);
heapify(data,largest,heapSize);
}
}
//交换函数
public static void swap(int[] array,int i,int j){
int temp =0;
temp=array[i];
array[i]=array[j];
array[j]=temp;
}
public static void main(String[] args) {
int[] arr = { 55, 56, 23, 90, 47, 9, 40, 82, 76, 33 };
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
System.out.print(",");
}
System.out.println();
heapSort(arr);
}
}
结果如下: