演算法 3 堆排序

2021-09-25 17:03:12 字數 3003 閱讀 5866

堆排序是一種選擇排序,其時間複雜度為o(nlogn)。

堆的定義

n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。

情形1:ki 

<= k2i 且ki 

<= k2i+1 (最小化堆小頂堆

情形2:ki >= k2i 且ki >= k2i+1 (化堆大頂堆

其中i=1,2,…,n/2向下取整;

若將和此序列對應的一維陣列(即以一維陣列作此序列的儲存結構)看成是乙個完全二叉樹,則堆的含義表明,完全二叉樹中所有非終端結點的值均不大於(或不小於)其左、右孩子結點的值。

由此,若序列是堆,則堆頂元素(或完全二叉樹的根)必為序列中n個元素的最小值(或最大值)。

例如,下列兩個序列為堆,對應的完全二叉樹如圖:

若在輸出堆頂的最小值之後,使得剩餘n-1個元素的序列重又建成乙個堆,則得到n個元素的次小值。如此反覆執行,便能得到乙個有序序列,這個過程稱之為堆排序

堆排序(heap sort)只需要乙個記錄元素大小的輔助空間(供交換用),每個待排序的記錄僅占有乙個儲存空間。

一般用陣列來表示堆,若根結點存在序號0處, i結點的父結點下標就為(i-1)/2。i結點的左右子結點下標分別為2*i+1和2*i+2。

(注:如果根結點是從1開始,則左右孩子結點分別是2i和2i+1。)

如第0個結點左右子結點下標分別為1和2。

如最大化堆如下:

左圖為其儲存結構,右圖為其邏輯結構。

實現堆排序需要解決兩個問題:

1.如何由乙個無序序列建成乙個堆?

2.如何在輸出堆頂元素之後,調整剩餘元素成為乙個新的堆?

先考慮第二個問題,一般在輸出堆頂元素之後,視為將這個元素排除,然後用表中最後乙個元素填補它的位置,自上向下進行調整:首先將堆頂元素和它的左右子樹的根結點進行比較,把最小的元素交換到堆頂;然後順著被破壞的路徑一路調整下去,直至葉子結點,就得到新的堆。

我們稱這個自堆頂至葉子的調整過程為「篩選」。

從無序序列建立堆的過程就是乙個反覆「篩選」的過程。

初始化堆的時候是對所有的非葉子結點進行篩選。

最後乙個非終端元素的下標是[n/2]向下取整,所以篩選只需要從第[n/2]向下取整個元素開始,從後往前進行調整。

比如,給定乙個陣列,首先根據該陣列元素構造乙個完全二叉樹。

然後從最後乙個非葉子結點開始,每次都是從父結點、左孩子、右孩子中進行比較交換,交換可能會引起孩子結點不滿足堆的性質,所以每次交換之後需要重新對被交換的孩子結點進行調整。

有了初始堆之後就可以進行排序了。

堆排序是一種選擇排序。建立的初始堆為初始的無序區。

排序開始,首先輸出堆頂元素(因為它是最值),將堆頂元素和最後乙個元素交換,這樣,第n個位置(即最後乙個位置)作為有序區,前n-1個位置仍是無序區,對無序區進行調整,得到堆之後,再交換堆頂和最後乙個元素,這樣有序區長度變為2。。。

不斷進行此操作,將剩下的元素重新調整為堆,然後輸出堆頂元素到有序區。每次交換都導致無序區-1,有序區+1。不斷重複此過程直到有序區長度增長為n-1,排序完成。

首先,建立初始的堆結構如圖:

然後,交換堆頂的元素和最後乙個元素,此時最後乙個位置作為有序區(有序區顯示為黃色),然後進行其他無序區的堆調整,重新得到大頂堆後,交換堆頂和倒數第二個元素的位置……

重複此過程:

最後,有序區擴充套件完成即排序完成:

由排序過程可見,若想得到公升序,則建立大頂堆,若想得到降序,則建立小頂堆

假設排列的元素為整型,且元素的關鍵字為其本身。

因為要進行公升序排列,所以用大頂堆。

根結點從0開始,所以i結點的左右孩子結點的下標為2i+1和2i+2。

void heapadjust(int h, int start, int

end)

if (temp > h[i])//

左右孩子中獲勝者與父親的比較

//將孩子結點上位,則以孩子結點的位置進行下一輪的篩選

h[start] =h[i];

start =i;

}h[start] = temp; //

插入最開始不和諧的元素

}

void heapsort(int a, int

n)

//進行排序

for (int i = n; i > 0; i--)

}

堆排序方法對記錄數較少的檔案並不值得提倡,但對n較大的檔案還是很有效的。因為其執行時間主要耗費在建初始堆和調整建新堆時進行的反覆「篩選」上。

堆排序在最壞的情況下,其時間複雜度也為o(nlogn)。相對於快速排序來說,這是堆排序的最大優點。此外,堆排序僅需乙個記錄大小的供交換用的輔助儲存空間。

演算法 3 堆排序

堆排序是一種選擇排序,其時間複雜度為o nlogn 堆的定義 n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。情形1 ki k2i 且ki k2i 1 最小化堆或小頂堆 情形2 ki k2i 且ki k2i 1 最大化堆或大頂堆 其中i 1,2,n 2向下取整 若將和此序列對應的一維陣列 即以一...

演算法 3 堆排序

堆排序是一種選擇排序,其時間複雜度為o nlogn 堆的定義 n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。情形1 ki k2i 且ki k2i 1 最小化堆或小頂堆 情形2 ki k2i 且ki k2i 1 最大化堆或大頂堆 其中i 1,2,n 2向下取整 若將和此序列對應的一維陣列 即以一...

演算法 3 堆排序

堆排序是一種選擇排序,其時間複雜度為o nlogn 堆的定義 n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。情形1 ki k2i 且ki k2i 1 最小化堆或小頂堆 情形2 ki k2i 且ki k2i 1 最大化堆或大頂堆 其中i 1,2,n 2向下取整 若將和此序列對應的一維陣列 即以一...