排序演算法之堆排序及其C語言程式碼實現
阿新 • • 發佈:2019-01-23
概述:堆排,實際上是一種選擇排序,只不過採用了堆這種資料結構,利用這種資料結構,使得在每次查詢最大元素時,直接選取堆頂元素,從而時間大大縮短,相對簡單選擇排序演算法來說,比較高效。
堆排序演算法可描述如下:
1.將待排元素依次存入陣列,該陣列即為一顆完全二叉樹;
2.從最後一個非葉節點開始遞減,逐次將每個相應的二叉樹調整成最大堆,最後,整個二叉樹即為最大堆;
3.交換堆頂元素與堆尾元素,調整新的堆為最大堆,陣列分為兩部分:堆與已排序列,直至最後一個堆元素。
從上面可以看出,堆排序大致可以分為三個步驟:
1.存入資料(完全二叉樹)
2.將前n個元素調整為最大堆
3.交換堆頂和堆尾元素,n=n-1,轉2
注:本文元素從陣列下標1開始儲存,所以parent訪問二叉樹左右兒子分別為2*parent 和 2*parent+1;
兩個核心函式:
void HeapAdjust(int H[],int start,int end)//堆調整,將start和end之間的元素調整為最大堆
void HeapSort(int H[],int L,int R)//堆排序
核心程式碼實現:
void HeapAdjust(int H[],int start,int end)//堆調整,將start和end之間的元素調整為最大堆
{
int temp=H[start];
int parent=start,child;
while(2*parent<=end)
{
child=2 *parent;
if(child!=end&&H[child]<H[child+1])++child;
if(temp>H[child])break;
else H[parent]=H[child];
parent=child;
}
H[parent]=temp;
}
void HeapSort(int H[],int L,int R)
{
for(int i=(R-L+1)/2;i>=L;--i)//調整整個二叉樹為最大堆
HeapAdjust(H,i,R);
for (int i=R;i>=L;--i)
{
swap(&H[L],&H[i]);
HeapAdjust(H,L,i-1);
}
}
測試樣例:
#include <stdio.h>
#define NA -1
void swap(int *a,int *b)//該函式用於交換兩個變數的值
{
int temp=*a;
*a=*b;
*b=temp;
}
void HeapAdjust(int H[],int start,int end)//堆調整,將start和end之間的元素調整為最大堆
{
int temp=H[start];
int parent=start,child;
while(2*parent<=end)
{
child=2*parent;
if(child!=end&&H[child]<H[child+1])++child;
if(temp>H[child])break;
else H[parent]=H[child];
parent=child;
}
H[parent]=temp;
}
void HeapSort(int H[],int L,int R)
{
for(int i=(R-L+1)/2;i>=L;--i)//調整整個二叉樹為最大堆
HeapAdjust(H,i,R);
for(int i=R;i>=L;--i)
{
swap(&H[L],&H[i]);
HeapAdjust(H,L,i-1);
}
}
int main(){
int A[]={NA,1,3,63,5,78,9,12,52,8};//從1開始存入資料
printf("Previous Arrary:");
for(int i=1;i<=9;++i)
printf(" %d",A[i]);
HeapSort(A,1,9);
printf("\nSorted Arrary:");
for(int i=1;i<=9;++i)
printf(" %d",A[i]);
printf("\n");
return 0;
}
執行結果:
Previous Arrary: 1 3 63 5 78 9 12 52 8
Sorted Arrary: 1 3 5 8 9 12 52 63 78
請按任意鍵繼續. . .
另:推薦一篇比較詳細的文章,讀者可以參看堆排序 Heap Sort