演算法導論第六章開始就開始介紹堆排序。
1. 計算堆中的孩子節點要仔細,因為堆排序用的是一位陣列表示二維二叉樹的概念的,這都是人為地把數值中的元素和二叉樹的乙個節點乙個節點地第一對應起來的,所以要程式設計師自己計算好這些對應關係。對二叉樹概念不夠熟悉的話,先要惡補一下。
2. 理解大堆頂化這個概念, 大堆頂化是使用遞迴法來進行,之所以這個演算法可行的關鍵是:1) 這個演算法只能應用於最大頂點mh的子樹都已經是大頂堆了,否則的話就是不可大頂堆化的; 2)所以這個演算法是從堆底起呼叫到對頂的。要理解乙個元素(也可以說乙個葉子)就肯定是大頂堆。
3. 因為是大頂堆,所以堆頂就肯定是所有元素中的最大值,所以每次都把最大值調到最後面,然後把最後面對應最大元素排除在堆外,再重新大頂堆化。比如說0到n個元素組成乙個大頂堆,那麼最後乙個元素是n,那麼第0個元素肯定是最大值,把第n個元素和第0個元素調換之後,那麼最大值是第n個元素,而第0個元素就不是最大值了。這個時候,再吧0到n-1個元素組成乙個大頂堆,那麼就需要把這個堆重新大頂堆化,得到乙個新的大頂堆,那麼同理第0個元素依然是最大的。
#include#includeusing namespace std;
//查詢堆排序中的節點父母,本例沒有用到
int heapleftchild(int i)
//查詢左孩子,注意其計算,一點也不能錯。
int heaprightchild(int i)
//查詢右孩子,小心計算
templateint trimax(vector& heap, int currentindex, int heapsize, int lchild, int rchild)
templatevoid maxheapify(vector& heap, int currentindex, int heapsize)
}//使用遞迴法來進行大頂堆化,之所以這個演算法可行的關鍵是:
//這個演算法只能應用於最大頂點currentindex的子樹都已經是大頂堆了,否則的話就是不可大頂堆化的
//所以這個演算法是從堆底起呼叫到對頂的。可以說乙個元素(也可以說乙個葉子)就肯定是大頂堆
templatevoid buildmaxheap(vector& heap, int heapsize)
//這裡必須從堆底起呼叫堆頂化maxheapify,否則是無法建立大頂堆的。
templatevoid heapsort(vector& heap)
}//因為是大頂堆,所以堆頂就肯定是所有元素中的最大值,所以每次都把最大值調到最後面,
//然後把最後面對應最大元素排除在堆外,再重新大頂堆化。
void test()
; vectorheap(a, a+18);
//排序前
for(int j=0; j<18; j++)
{ cout《演算法有點難理解,不過多過幾遍就應該也可以的了,注意畫圖幫助理解,手動走一走程式。
程式設計書寫一定要規範,變數命名一定要有意義,不能因為程式小而忽略這些方法,不然會養成壞習慣的,而且也不利於程式除錯。不能貪圖方便,快,而隨便挑乙個簡短的命名變數。
這是我注釋得最詳細的程式之一了,希望都能看懂吧。
而且我這裡有點創新之處的就是抽多乙個trimax函式出來,我發現這樣更方便理解,大家可以把這個程式和演算法導論的對比一下有什麼不一樣。
注意其中的邏輯細節,否則很容易出錯的。
演算法資料結構C 實現8 堆排序 難點分析
演算法導論第六章開始就開始介紹堆排序。1.計算堆中的孩子節點要仔細,因為堆排序用的是一位陣列表示二維二叉樹的概念的,這都是人為地把數值中的元素和二叉樹的乙個節點乙個節點地第一對應起來的,所以要程式設計師自己計算好這些對應關係。對二叉樹概念不夠熟悉的話,先要惡補一下。2.理解大堆頂化這個概念,大堆頂化...
資料結構與演算法 資料結構C 堆
資料結構c 堆 如果有乙個關鍵碼的集合k 把它的所有元素按完全二叉樹的順序儲存方式儲存在乙個一維陣列中,並滿足 ki k2 i 1 且 ki k2 i 2 ki k2 i 1 且 ki k2 i 2 i 0,1,2 則稱為小堆 或大堆 小堆 大堆 中 任一結點的關鍵碼均小於 大於 等於它的左右孩子的...
資料結構和演算法 堆和堆排序
堆是一種特殊的樹,他有倆個要求 1 堆是乙個完全二叉樹 2 堆每乙個節點的值,都大於等於 或小於等於 其左右子樹節點的值 解釋一下 第一點,完全二叉樹就是除了最後一層,其它層的節點數都是滿的,最後一層的節點都靠左排列 每個節點都大於等於左右子樹節點的叫做大頂堆,每個節點都小於等於左右子樹節點的叫做小...