基礎知識 之 堆排序(heap sorting)

2022-03-15 21:15:23 字數 3006 閱讀 8645

sorting

比較好的排序演算法可以把時間複雜度控制在o(n*log2n),最糟的情況是o(n2).

應該將sort當作一項基礎處理,因為對於很多問題,當其資料變成sorted items時,解決起來會很容易。

stable sorting

對於key相同的元素,有時我們需要保持它們原先的順序。但不幸的是,很少有快速演算法是stable的。不過,我們可以將元素的位置作為第二參考量,當元素a.key = b.key時,原先位置小的仍然排在前面。

選擇排序(selection sort)

選擇排序就是將乙個item list分為兩部分,一部分是sorted,一部分是unsorted。每次都從unsorted的部分中取出最小的值,與索引位置i所在的元素進行交換,交換後,索引i加1;一直這樣下去,知道整個list完成排序。

交換乙個元素所需的時間為o(1),但是在unsorted部分中尋找最小值則需要耗費o(n)的時間,這樣所有的元素排序一趟下來需要的時間為o(n2)。在這個過程中,如果能優化unsorted的部分,讓在其中尋找最小值的時間複雜度變小就可以優化整個選擇排序演算法,例如,如果把unsorted的部分改為balance tree結構的話,那麼在其中尋找最小值的時間複雜度將下降至o(log2n),那麼總的時間複雜度將下降至o(n*log2n)。

堆排序就是改進了資料結構的選擇排序演算法。

堆(heap)

堆是一種特別的結構,它的有序性比sorted order差,但是又比random order強。

例如最小堆(即某元素的父節點總比自己小,最大堆則正好相反)

它儲存到陣列中為:

堆的特點是它是乙個完全二叉樹,因此,它可以利用陣列來方便地儲存其樹狀結構(而不需要像二叉搜尋樹一樣還需要額外的指標來維護樹結構)。

對於完全二叉樹,有如下特點:

①第l層的節點位於陣列的2l-1至2l-1的位置

②對於節點k,其左孩子位於2k,右孩子位於2k+1,其父節點位於k/2

但它也有一些缺點,比如無法快速搜尋到乙個某個節點,只能用廣搜一圈圈地搜,平均時間複雜度為o(n/2)

堆的構建

堆的構建採用冒泡的方式(ps:不是冒泡演算法的那個冒泡)

對於乙個新的元素k,將其放在陣列的最後,然後將它與自己的父節點進行比較,若它比自己的父節點小(假設構建的是最小堆),那麼將它與自己的父節點交換;一直這樣往上冒泡,直到有乙個父節點比自己小或者冒到根節點為止。

ps:父節點的位置為k/2.

堆節點的摘除

在使用堆來做選擇排序時(也就是堆排序),會不停的摘掉堆的頂。

將堆的頂點摘除後,會留下乙個洞,這時可以把陣列的第n個(即最後乙個元素)放置到頂部暫時充當根節點,然後將該節點和它的左孩子(2k)、右孩子(2k+1)進行比較,將三者中小的那個換到父節點的位置上;一直這樣下去直到堆重新穩定(即父節點是比左孩子、右孩子都小)。

ps:頂點摘除後,將最後乙個元素暫移至root處,然後開始往下冒泡。

快速建立堆的小竅門

假設有n個元素,那麼第n個元素的父節點為n/2,也就是說從n/2以後的元素均為葉子節點。所以,在構建堆的時候,我們可以先填滿後n/2個元素。

例如:1945 1865 1963 1776 1492 1783 1918 2001 1941 1804,我們將5個元素從下往上填

現在開始從下往上填第六個元素

現在開始往下冒泡,k=5,故2k=10,2k+1=null,所以,對比 array[5]=1783 和 array[10]=1945,顯然1783 < 1945,故不需要進行交換。即在父節點、左孩子、右孩子中,父節點(1783)勝出。

接著,我們再從下往上填第七個元素

然後再進行父節點、左孩子、右孩子的遞迴比較

顯然9號元素1865勝出,因此將4號元素與9號元素進行交換,變成

交換後,k變成9,由於2k=18不存在,因此遞迴終止。

接著,我們再從下往上填寫第八個元素,即 2001

然後進行父節點、左孩子、右孩子的遞迴比較

6號元素1492勝出,因此將3號元素與6號元素換位

現在,k變成6,由於2k=12不存在,因此此次遞迴終止。

接下來再一次從下往上填寫第九個元素1941,遞迴比較換位後,再填寫第十個元素1804,再進行遞迴比較換位。最終的結果為:

堆排序

在建立完堆結構以後,進行堆排序的過程就是摘頂,調整堆結構,再摘頂,再調整堆結構,直到堆被摘完為止,這樣就可以得到乙個有序序列。

十大基礎實用演算法補全 堆排序(HeapSort)

1991年的計算機先驅獎獲得者 史丹福大學電腦科學系教授羅伯特 弗洛伊德 robert w floyd 和威廉士 j williams 在1964年共同發明了著名的堆排序演算法 heap sort 在了解堆排序演算法的原理之前,我們必須先來了解一下什麼是堆?堆就是乙個近似的完全的二叉樹。那什麼又是完...

9 7 堆排序基礎知識準備

堆排序基礎知識 include 堆排序 因為堆是一棵完全二叉樹,固可用陣列來表示 const int maxn 100 int heap maxn n 10 heap 為堆,n為元素個數 堆由上向下調整 將每個結點v與其孩子比較,若有比其大的,則交換他們的位置 直到沒有比他大的或沒有孩子結點 對he...

排序01 基礎知識

一 排序的定義 所謂排序,就是要整理檔案中的記錄,使之按關鍵字遞增 或遞減 次序排列起來。其確切定義如下 輸入 n個記錄r1,r2,rn,其相應的關鍵字分別為k1,k2,kn。輸出 ril,ri2,rin,使得ki1 ki2 kin。或ki1 ki2 kin 二 排序的分類 1 按是否涉及資料的內 ...