堆排序算法(選擇排序改進(jìn))
首先要理解堆的含義:要么所有節(jié)點都不大于其子孩子節(jié)點數(shù)據(jù),要么都不小于其子孩子節(jié)點數(shù)據(jù)
堆排序的核心思想:就是要滿足所有節(jié)點都滿足上面兩點,如何完成,看下面
堆排序的步驟:
1.首先要建成一個大頂堆或者小頂堆,在建的過程中其實就是調(diào)整節(jié)點的位置,首先要從最后最后一個節(jié)點的母親節(jié)點開始,按照堆的含義調(diào)整。為什么不是最后一個或者其他?因為要保證完整性和不必要性,所以只需從最后一個的母親節(jié)點開始即可(下面的堆默認(rèn)存在順序結(jié)構(gòu),從索引0開始的,所以有些二叉樹的特性請查閱二叉樹),直至索引節(jié)點為0的節(jié)點。調(diào)整完成后即成為一個堆,但是這里的數(shù)據(jù)并沒有排序好,所以下一部調(diào)整順序。
2.從最后一個數(shù)據(jù)開始,與第一個數(shù)據(jù)進(jìn)行交換,然后按照堆的含義調(diào)整第一個數(shù)據(jù)。為什么先選擇最后一個數(shù)據(jù)?因為默認(rèn)情況下,最后一個或者是較大或者是較小,可以滿足調(diào)整要求。這時就考慮當(dāng)前所有數(shù)據(jù)減去最后一個,因為這個已是最大或者是最小,不必再考慮.。直至調(diào)整沒有任何數(shù)據(jù),此時已完成排序。
具體圖例不再標(biāo)識,有此愛好可以參考其他書籍或者網(wǎng)上的介紹,下面看堆排序代碼:
int HeapSort(MergeType* L)
{
int i = 0;
if (!L->elem)
{
return -1;
}
//創(chuàng)建堆
for (int i = L->len/2-1; i >= 0; i--)
{
HeapAdjust(L, i, L->len-1);
}
//堆排序
for (i = L->len-1; i >= 0; i-- )
{
swap(L->elem[i], L->elem[0]);
HeapAdjust(L, 0, i-1);
}
return 0;
}
注意:
1)由于父子節(jié)點的關(guān)系,for循環(huán)第一個數(shù)據(jù)索引其實是L,len-1,但是其父母節(jié)點(i)與 當(dāng)前節(jié)點(p)的關(guān)系:p = 2i+1 或者2i+2; 如果存儲數(shù)據(jù)的節(jié)點第一個索引不是0而是1,這里p=2i或者p=2i+1,請參看有關(guān)書籍的證明,所以當(dāng)前父母節(jié)點:i =(p-1)/ 2 = (L.len-1-1)/2 = L.len/2-1
2)由于再次調(diào)整數(shù)據(jù)的時候是從最后一個數(shù)據(jù),所以需要交換數(shù)據(jù)swap,再進(jìn)行當(dāng)前頂點數(shù)據(jù)也就是第一個數(shù)據(jù)的堆調(diào)整,但是此時調(diào)整的對象只是(0~i)這些數(shù)據(jù),其他已經(jīng)排序好,所以不再需要調(diào)整
下面看一下調(diào)整代碼,如下:
int HeapAdjust(MergeType* L, int nPos, int nEnd)
{
for (int i = nPos*2+1; i < nEnd ; i = 2*i+1)
{
if (L->elem[i] <= L->elem[i+1])
{
i++;
}
if (L->elem[nPos] >= L->elem[i])
{
break;
}
swap(L->elem[nPos], L->elem[i]);
nPos = i;
}
return 0;
}
這里使用的是在一個層次上是數(shù)據(jù)直接交換,其實這不是必須的,因為最后才把數(shù)據(jù)放到最后的位置,所以也可以使用下面的代碼,減少復(fù)制的次數(shù)
int HeapAdjustEx(MergeType* L, int nPos, int nEnd)
{
int nTempkey = L->elem[nPos];
for (int i = nPos*2+1; i < nEnd ; i = 2*i+1)
{
if (L->elem[i] <= L->elem[i+1])//選出最大的子孩子
{
i++;
}
if (nTempkey >= L->elem[i]) //如果當(dāng)前節(jié)點大于最大子孩子退出
{
break;
}
L->elem[nPos] = L->elem[i]; //否則進(jìn)行數(shù)據(jù)交換
nPos = i;
}
L->elem[nPos] = nTempkey;
return 0;
}
這里就可以減少較多的復(fù)制操作,也就是俗稱的移動操作次數(shù);這里for循環(huán)的起始節(jié)點按照上面的推論,子節(jié)點應(yīng)該為p=2i+1,所以第一個應(yīng)該為2*nPos+1,對應(yīng)當(dāng)前要比較節(jié)點的做孩子,右孩子為2*nPos+2,也就是左孩子+1,其他請看注釋。
時間復(fù)雜度:O(nlogn),分析過程暫略
上一篇:C中qsort快速排序使用實例
欄 目:C語言
本文標(biāo)題:堆排序算法(選擇排序改進(jìn))
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3823.html
您可能感興趣的文章
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入第K大數(shù)問題以及算法概要的詳解
- 01-10深入N皇后問題的兩個最高效算法的詳解
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10深入全排列算法及其實現(xiàn)方法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)
- 01-10深入理解堆排序及其分析
- 01-10深入單鏈表的快速排序詳解
- 01-10貪心算法 WOODEN STICKS 實例代碼


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法