程式設計師必須掌握的十種演算法---堆排序演算法
阿新 • • 發佈:2019-01-03
堆排序,就是利用完全二叉樹的某些特性對陣列進行排序。
#include<stdio.h>
int h[101];//用來存放堆的陣列
int n;//用來儲存堆中元素的個數,也就是堆的大小
//交換函式,用來交換堆中兩個元素的值
void swap(int x,int y)
{
int t;
t=h[x];
h[x]=h[y];
h[y]=t;
}
//向下調整函式
//傳入一個需要向下調整的結點編號i,
//這裡傳入1,是從堆的頂點開始向下調整
void siftdown(int i)
{
int t,flag=0;//flag用來標記是否需要繼續向下調整
//當i結點有兒子(其實是至少有左兒子),並且有需要繼續調整的時候迴圈
while(i*2<=n&&flag==0)
{
//首先判斷它和左兒子的關係,並用t記錄值較大的結點編號
if(h[i]<h[i*2])
t=i*2;
else
t=i;
//如果有右兒子,再對右兒子進行討論
if(i*2+1<=n)
{
//如果右兒子值更小,更新較大的結點編號
if(h[i]<h[i*2+1])
t=i*2+1 ;
}
//如果發現最大的結點編號不是自己,說明子節點中有比父節點更大的
if(t!=i)
{
swap(t,i);//交換他們
i=t;//更新i為剛才與它交換的兒子結點的編號,便於接下來繼續向下調整
}
else
flag=1;//說明當前結點比兩個子節點都要大,不需要在進行調整了
}
}
//建立堆的函式
void creat()
{
int i;
//從最後一個非葉結點到第一個結點依次向上調整
for(i=n/2 ;i>=1;i--)
{
siftdown(i);
}
}
//堆排序
void heapsort()
{
while(n>1)
{
swap(1,n);
n--;
siftdown(1);
}
}
int main()
{
int i,num;
//讀入要排序的數字的個數
scanf("%d",&num);
for(i=1;i<=num;i++)
scanf("%d",&h[i]);
n=num;
//建堆
creat();
//堆排序
heapsort();
//輸出
for(i=1;i<=num;i++)
printf("%d ",h[i]);
getchar();
getchar();
return 0;
}
以上程式碼參考《啊哈!演算法》這本書,如果想更仔細的瞭解這些內容,推薦大家去看這本書。