堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分爲大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因爲根據大根堆的要求可知,最大的值一定在堆頂。
高度
C語言
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#include <stdio.h> //array是待調整的堆數組,i是待調整的數組元素的位置,nlength是數組的長度 //本函數功能是:根據數組array構建大根堆 void HeapAdjust( int array[], int i, int nLength) { int nChild; int nTemp; for (;2*i+1<nLength;i=nChild) { //子結點的位置=2*(父結點位置)+1 nChild=2*i+1; //得到子結點中較大的結點 if (nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild; //如果較大的子結點大於父結點那麼把較大的子結點往上移動,替換它的父結點 if (array[i]<array[nChild]) { nTemp=array[i]; array[i]=array[nChild]; array[nChild]=nTemp; } else break ; //否則退出循環 } } //堆排序算法 void HeapSort( int array[], int length) { int i; //調整序列的前半部分元素,調整完之後第一個元素是序列的最大的元素 //length/2-1是最後一個非葉節點,此處"/"爲整除 for (i=length/2-1;i>=0;--i) HeapAdjust(array,i,length); //從最後一個元素開始對序列進行調整,不斷的縮小調整的範圍直到第一個元素 for (i=length-1;i>0;--i) { //把第一個元素和當前的最後一個元素交換, //保證當前的最後一個位置的元素都是在現在的這個序列之中最大的 array[i]=array[0]^array[i]; array[0]=array[0]^array[i]; array[i]=array[0]^array[i]; //不斷縮小調整heap的範圍,每一次調整完畢保證第一個元素是當前序列的最大值 HeapAdjust(array,0,i); } } int main() { int i; int num[]={9,8,7,6,5,4,3,2,1,0}; HeapSort(num, sizeof (num)/ sizeof ( int )); for (i=0;i< sizeof (num)/ sizeof ( int );i++) { printf ( "%d " ,num[i]); } printf ( "\nok\n" ); return 0; } |
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
//堆排序 //整理節點time:O(lgn) template <typenameT> void MinHeapify(T*arry, int size, int element) { int lchild=element*2+1,rchild=lchild+1; //左右子樹 while (rchild<size) //子樹均在範圍內 { if (arry[element]<=arry[lchild]&&arry[element]<=arry[rchild]) //如果比左右子樹都小,完成整理 { return ; } if (arry[lchild]<=arry[rchild]) //如果左邊最小 { swap(arry[element],arry[lchild]); //把左面的提到上面 element=lchild; //循環時整理子樹 } else //否則右面最小 { swap(arry[element],arry[rchild]); //同理 element=rchild; } lchild=element*2+1; rchild=lchild+1; //重新計算子樹位置 } if (lchild<size&&arry[lchild]<arry[element]) //只有左子樹且子樹小於自己 { swap(arry[lchild],arry[element]); } return ; } //堆排序time:O(nlgn) template <typenameT> void HeapSort(T*arry, int size) { int i; for (i=size-1;i>=0;i--) //從子樹開始整理樹 { MinHeapify(arry,size,i); } while (size>0) //拆除樹 { swap(arry[size-1],arry[0]); //將根(最小)與數組最末交換 size--; //樹大小減小 MinHeapify(arry,size,0); //整理樹 } return ; } |