堆排學習筆記

2022-06-07 12:00:18 字數 1661 閱讀 5110

堆排的本質是構成乙個二叉樹,其二叉樹的特性是子樹都比其父親的數值要小(針對從大到小的排序而言,這種樹叫最大堆)

堆排序一共分成三步

1.構建初始二叉樹,將本無序的堆疊,以最大堆的形式重新構造,以便於接下來的步驟的進行

2.將最大的數字(位於樹的根部)和最底端的數字交換(換到陣列最後面),再將最底端被交換的那個數字(此時已經被換到了樹的根部)沉沒下去,使二叉樹再次變成乙個最大堆(不算被交換到陣列底部的那個數字),接著再次重複此步驟

3.完成所有步驟之後,按順序列印,即可獲得乙個從大到小的序列

圖源:

第一步:構造的過程:從最後乙個節點開始遍歷,每次走到乙個節點時:比較它的父親,兄弟,以及它自己三者大小,並且將最大的移到父親的位置

構造結束後,堆中的情況:

第二步:交換的過程

第三步:列印的過程,不再贅述

明白思路過後,就要搞出乙份**來,下面是我的各個步驟的**,每個人的**風格格式均不相同,僅供參考

下沉過程:down

1

void down(int x)//

把小的元素下沉 x是數字在陣列中的位置 n代表陣列中未完成排序的數的總量 210

else

if(number[x*2+1]<=number[x*2])//

如果左兒子比右兒子大,交換該節點和它的左兒子

1115

else

if(number[x*2+1]>number[x*2]&&x*2+1>n)//

特殊情況,右兒子大於左兒子,但是右兒子是已經排序完的數字,不可以交換

1619

}20 }

上浮過程:up

1

void up(int x)//

把大的元素上浮

29 }

在陣列尾端插入新數:insert

1

void insert(int newnumber)//

插入新的數字進入堆中

2

主函式:

因為使用堆的情況不同,這裡我就不放我的主函式了,簡要說明一下堆排主函式大致的實現方法

1.將每個數字用insert函式插入到陣列中,使其一直保持為乙個最大堆(或最小堆)

2.將根節點和陣列最後的節點交換,並將n減少1,此後的操作不再改變該數字在陣列中的位置

3.將被轉移到現在的根節點的位置的數,沉沒下去,以便該堆仍為乙個最大堆,也保證了沉沒後的堆的根節點是最大值(除了被處理完的數以外最大)

4.重複2.3兩步直到n==1為止

5.此時的陣列就是乙個從小到大順序排列好的陣列

以上就是堆排的主要操作的過程,其中,下沉過程中的if 判斷很值得思考,我在第一次使用堆排的時候發生了很嚴重的錯誤,因為沒有考慮全if的條件導致最後發生死迴圈。

如果您也是一位初學者,我非常建議您在理解堆排的過程中不僅要自己敲一遍**,還應該畫出堆中節點的swap過程,這樣有助於理解和記憶。

希望我的這篇學習筆記對您的學習有所幫助。

堆排的學習

堆排沒有用到遞迴,一般堆排是兩個步驟,1 建立堆 2 不斷的調整堆,進行排序 首先,我們學習堆排就必須了解什麼是堆,堆其實是一種比較特殊的資料結構,分為大根堆和小根堆,堆有兩個性質 1 它是乙個完全二叉樹,每個節點都比它的子樹所有節點大 大根堆 2 由於他是乙個完全二叉樹,那麼它的每個位置都與陣列的...

快排和堆排

一 快速排序 最常用的排序演算法,速度通常也是最快的。時間複雜度 o nlogn 最壞 o n 2 空間複雜度 o nlgn 不穩定 比如 5 3 3 4 3 8 9 10 11 這個序列,在中樞元素5和3交換就會把元素3的穩定性打亂 實現原理 快排主要是通過選擇乙個關鍵值作為基準值。比基準值小的都...

快排 歸併 堆排

快排 include include include includeusing namespace std void quicksort vector a,int l,int r 終止遞迴的條件,子串行長度為1 int mid low high low 2 取得序列中間的元素 mergesort a...