C語言數(shù)據(jù)結(jié)構(gòu)之堆排序詳解
1.堆的概念及結(jié)構(gòu)
如果有一個關(guān)鍵碼的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉樹(二叉樹具體概念參見——二叉樹詳解)的順序存儲方式存儲在一個一維數(shù)組中,并滿足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,則稱為小堆(或大堆)。將根節(jié)點最大的堆叫做最大堆或大根堆,根節(jié)點最小的堆叫做最小堆或小根堆。

堆的性質(zhì):
- 堆中某個節(jié)點的值總是不大于或不小于其父節(jié)點的值;
- 堆總是一棵完全二叉樹。
2.堆的實現(xiàn)
堆的實現(xiàn)請參見——二叉樹詳解(堆的實現(xiàn))
2.1 堆的向下調(diào)整算法
(此文章都已建小堆為例)
向下調(diào)整算法前提:當前樹左右子樹都是小堆
核心思想:選出左右孩子中小的那個,和父親交換,小的往上浮,大的往下沉,這里是小堆,如果是大堆則相反。

代碼實現(xiàn)
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
//堆向下調(diào)整算法
void AdjustDown(int *a, int n, int root)
{
int parent = root;
int child = parent * 2 + 1;
while (child<n)
{
//保證孩子節(jié)點child為兩個孩子中的最小值;保證不越界
if (a[child] > a[child + 1] && child+1 < n)
++child;
if (a[child] < a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
2.2 堆的向上調(diào)整算法
使用場景:向上調(diào)整算法適用于向堆中插入數(shù)據(jù),當向堆中插入數(shù)據(jù)就可能會導致堆失去大堆或者小堆的性質(zhì),此時需要重新調(diào)整,向上調(diào)整的思路與向下調(diào)整算法的思路類似,向上調(diào)整算法只需要從插入結(jié)點位置開始和父節(jié)點比較。
圖示:

代碼實現(xiàn):
void AdjustUp(int *a, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[parent] > a[child])
{
swap(&a[parent], &a[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
2.3 建堆(數(shù)組)
從最后一個非葉子節(jié)點位置行依次開始調(diào)整,如圖:

代碼實現(xiàn):
int parent = (n-2) / 2;
//首先對每一個非葉子節(jié)點進行一次向下調(diào)整算法,保證每個非葉子節(jié)點的
//孩子都小于它的父節(jié)點,然后可得到最小值,就在堆的頂端的父節(jié)點(也叫做建小堆)
while (parent >= 0)
{
AdjustDown(a, n, parent);
--parent;
}
2.4 堆排序
升序建大堆,降序建小堆
void HeapSort(int *a, int n)
{
int parent = (n-2) / 2;
//首先對每一個非葉子節(jié)點進行一次向下調(diào)整算法,保證每個非葉子節(jié)點的
//孩子都小于它的父節(jié)點,然后可得到最小值,就在堆的頂端的父節(jié)點(也叫做建小堆)
while (parent >= 0)
{
AdjustDown(a, n, parent);
--parent;
}
int end = n-1;
while (end>0)
{
//將堆頂?shù)臄?shù)與最后的end,以此循環(huán),進行交換就可得到有序序列
//注意:建小堆,得到降序序列
swap(&a[end], &a[0]);
AdjustDown(a, end, 0);
--end;
}
}
2.5 堆排序的時間復(fù)雜度

所以建堆時間復(fù)雜度為O(N);
向下調(diào)整算法時間復(fù)雜度 O(logN);
所以堆排序的時間復(fù)雜度為 O(N*logN)
以上就是C語言數(shù)據(jù)結(jié)構(gòu)之堆排序詳解的詳細內(nèi)容,更多關(guān)于C語言堆排序的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
linux c程序中獲取shell腳本輸出的實現(xiàn)方法
以下是對在linux下c程序中獲取shell腳本輸出的實現(xiàn)方法進行了詳細的分析介紹,需要的朋友可以過來參考下2013-08-08
基于C++ list中erase與remove函數(shù)的使用詳解
本篇文章是對C++ list中erase與remove函數(shù)的使用進行了詳細的分析介紹,需要的朋友參考下2013-05-05

