首先來引入乙個例子:如何使用選擇排序?
肯定是每一次遍歷然後把大的放到最後面。(當然,前面也可以)
我感覺堆排序其實和選擇差不多。
堆排序也是每次取出最大值,然後把最大值放後面
但是想學會堆排序,首先要知道什麼是堆
#堆的定義
邏輯上:乙個完全二叉樹
物理上:借助向量實現
為什麼能用乙個向量來間接的弄乙個完全二叉樹呢?
(你自己試試把這個完全二叉樹按層次遍歷,是不是就是這個向量了)
如圖,因為完全二叉樹中間沒有空缺,都是連續的,所以可以把完全二叉樹存到陣列中,這樣就形為陣列,神為完全二叉樹。
#堆序性
就是說所有父親的值大於孩子的值(等等你就知道為啥了,先記著:-d)
介紹一下下濾演算法:
應該如何刪除最上面的父親?
對二叉樹熟悉的你一定知道,如果要刪除上面的,是先把最上面的和它右子樹的最左邊的那個葉子換位置,然後刪除。
但是這樣是不行的,首先:這個不是乙個那樣的樹,不是都是順序的。其次:這樣做會破壞向量的有序性,導致後面都出錯
應該把最後面的和最上面的交換,然後把新來的最上面的通過下濾操作重新變為堆就行了。
(j是你要讓第幾個下濾,n是總數(包括0))
void percolatedown(int *a,int j,int n)
return;
} int maxs = max(a,j * 2 + 1);
if(a[maxs] > a[j])
else}}
(因為神為二叉樹,所以時間為o(logn))
如何讓父親的值大於孩子的值呢?
利用下濾操作,自上到下的都有序就行了
(**中的i是總數,算0的,這樣寫方便)
void heapify(int *a,int i)
}
那麼最重要的來了,如何進行堆排序呢?
每次把最大的值假裝刪除(實際是把最大的值移動到最後面),然後讓總數-1就行了。
void sorts(int *a,int i)
}
堆排序演算法解析
堆排序是利用堆的性質進行的一種選擇排序。下面先討論一下堆。11.堆堆實際上是一棵完全二叉樹,其任何一非葉節點滿足性質 key i key 2i 1 key i key 2i 2 或者key i key 2i 1 key key 2i 2 即任何一非葉節點的關鍵字不大於或者不小於其左右孩子節點的關鍵字...
堆排序解析
首先要了解堆的性質,我這裡簡答總結一下 這裡說的是小堆 1 堆是一棵完全二叉樹 2 對於大堆中的任何乙個非葉子節點,節點的值必須小於左右孩子節點值。由此可知,對於小堆而言,根節點就是最小值了,那麼我們每次拿走根節點,拿走的順序就是遞增序列的。排序的元素在陣列中,而堆也是一棵完全二叉樹,所以直接用陣列...
深度解析堆排序
堆排序,其實就是用陣列儲存,利用完全二叉樹的性質,對其進行二叉樹的操作,通過構建大頂堆 小頂堆 找到最大值 最小值 與最後乙個節點交換,然後總個數減一,然後重複此操作,最後得到有序序列。如果不理解大頂堆與小頂堆的話,建議先看看 基本思路是 構建出始堆 將堆頂元素與最後乙個節點交換 遞迴此操作。感覺思...