堆排序主要思想:
1.初始化數串成大頂堆(或小頂堆)
1.1 先初始化一個非葉節點的小子樹爲大頂堆(或小頂堆)
1.2 再初始化數串中的每個子樹成大頂堆(或小頂堆)
2.由步驟1中得到的堆頂即是當前未排序數串的最大值。由此繼續循環得到下個最大值
堆排序與選擇排序有點相似,都是先通過循環比較得到 未排序數串中的最大值,然後把它給已排序的數串中。
但是選擇排序中循環比較時會出現很多重複比較的情況,而堆排序中則可以保存部分比較的結果
堆排序的平均複雜度比較接近O(nlogn),而選擇排序爲O(n^2)
代碼一:
/*
**該函數使一個含有父子節點的小子樹形成一個大頂堆
**array是要排序的數組
**father是父節點(它的值代表它是數組中的第幾個,不是下標)
**size是要排序數組的大小
*/
int smallheap(int array[], int father, int size)
{
int max = father; //用於暫存父子節點之間哪個最大,這裏首先假設父節點最大
int rchild = father * 2 + 1;
int lchild = father * 2;
if(rchild - 1 < size && array[rchild-1] > array[max-1]) //右節點與第max個數(這裏是父節點)比較
max = rchild;
if(lchild - 1 < size && array[lchild-1] > array[max-1]) //左節點與第max個數比較
max = lchild;
if(max != i) //如果父節點和子節點沒發生交換
{
swap(array[max-1],array[father-1]); //某個子節點(第max個)與父節點交換
smallheap(array, max, size); //交換後。遞歸檢查以第max個節點爲父節點的子樹是否滿足堆
}
return 0;
}
/*
**從數組後面逐漸往前掃描,依次把每個非葉節點的小子樹初始化成大頂堆
**array是要排序的數組
**size是要排序數組的大小
*/
int init(int array[], int size)
{
for(int i = size/2; i > 0; i--) // size/2 是最末的一個非葉節點
{
smallheap(array,i,size);
}
return 0;
}
/*
**循環得到未排序的數當中的最大值(最大父節點),
**並把它交換到後面,這樣已排序的數逐漸增多
**array是要排序的數組
**size是要排序數組的大小
*/
int heap_sort(int array[],int size)
{
init(array,size);
for(int i = size; i > 1;)
{
swap(array[0],array[i-1]); //最大父節點與未排序數串中的末位交換
smallheap(array,1,--i); //重新調整未排序(大小爲--i)的數串爲大頂堆
}
return 0;
}
int main()
{
int array[] = {2,3,44,77,66,7,4,10,55,3333};
heap_sort(array,10);
for(int i = 0; i < 10; i++)
printf("%d ",array[i]);
return 0;
}
-----本人菜鳥一隻,如有錯誤,望大牛們指出^_^