定義堆:堆是一棵完全二叉樹,完全二叉樹是指樹的每一層節點都被填滿,除了最後一層,最後一層
節點也要要求從最左邊開始連續的排。
通常用乙個陣列儲存堆:如下圖所示
可見用陣列儲存堆就是按照層次遍歷的順序將堆中各個元素存入陣列,下面計算堆中元素在陣列中的指標位置。
假設堆中元素a位於堆的第 i 層 第 j 列,堆的根節點幾位第 0 層,則可計算 a 在陣列的位置(從1開始)為
t_p=\sum_^2^k+j = 2^i+j-1.
a的子女節點位於第 i+1 層第 2( j-1 )+(0,1) 列,因此陣列指標
t_c=2^+2( j-1 )+(0,1)
觀察易知: t_c/2 = t_p+ (0,1/2);
t_c/2取整就位 t_p (父節點)
t_p*2 = t_l(左子女), t_p*2+1 = t_r(右子女)
最大堆定義:堆中任何乙個節點的值不小於它的子女節點的值
堆排序的第一步是建堆。
首先給出演算法的第一步乙個節點沿路徑下沉:
(1)對於任何選擇的節點,比較其與左右子女節點的大小,選擇最大的乙個與父親節點交換,在同樣考慮
交換後的下沉節點,直到節點下沉到葉子節點或者節點不在下沉為止。
這一步使得被選節點沿著下沉路徑處於合適的位置而不影響其他路徑。
現在假設節點的左右子樹均為最大堆,則左右子樹的任何一條路徑自上而下是遞減的,當所選節點沿著適當
路徑下沉到合適的位置時,容易知道新的以所選節點為根的子樹成為最大堆。
(2)從樹的最底部的第乙個非葉子節點開始按照上述第一步將所有的節點下沉。
由於葉子節點都為最大堆,從而由歸納法知道,當根節點下沉後,整個堆就成為最大堆,建堆過程完成。
(3)每次從堆的根節點取出元素,將最後乙個節點放入根部,進行一次下沉操作。
經過n次的這種操作完成整個排序,每次下沉需要logn的工作量,則總的演算法複雜度是:o(nlogn).
堆排序演算法的c++實現:
一、stl實現
利用c++的stl庫向量來管理堆的儲存,注意這裡的模板類t預設具有比較大小的功能
vectorheap.h 檔案
//此程式為實現堆排序演算法,用到stl中的vector類二、自定義陣列儲存實現//注意當vectorheap被例項化成物件時並不是乙個堆,必須在呼叫內部成員函式buildmaxheap()後成為最大堆
//2011/3/24 肖成
#ifndef _vector_heap
#define _vector_heap
#include using namespace std;
templateclass vectorheap
;templatevectorheap::vectorheap(vectorvec)
templatevectorheap::vectorheap(t*first, t*last)
templateint vectorheap::getleft(unsigned i)
templateint vectorheap::getright(unsigned i)
templatevoid vectorheap::maxheapify(int i)
}templatevoid vectorheap::buildmaxheap()
templatevoid vectorheap::deleteroot()
templatevectorvectorheap::sortheap()
return result;
}templateint vectorheap::getparent(int i)
templatevectorvectorheap::getdata()
#endif
自己管理陣列大小比較麻煩,因此**也會比較複雜
heapvec.h 檔案
//此程式為實現堆排序演算法,內部記憶體動態管理機制自己實現,類似於stl中的vector類三、下面給出測試性例子//注意當heapvec被例項化成非空物件即是乙個堆
//2011/3/24 肖成
#ifndef _heap_define
#define _heap_define
#include templateclass heap
;templateheap::heap()
templateheap::heap(t *dat, int size)
templateheap::heap(heap& hp)
templatevoid heap::clear()
}templatevoid heap::cutsize(int size)
templatevoid heap::deleteroot()
templateint heap::getleft(int i)
templateint heap::getright(int i)
templateint heap::getparent(int i)
templatet heap::getroot()
templateint heap::getsize()
templatevoid heap::insertvalue(t value)
else
break; }}
templatevoid heap::setroot(t value)
templatet heap::getvalue(int index)
}templatevoid heap::buildmaxheap()
templatet* heap::sortheap()
return result;
}templatevoid heap::setdata(t* dat, int s)
#endif
main.cpp
檔案
// main.cpp : 定義控制台應用程式的入口點。//#include #include "heapvec.h"
#include "vectorheap.h"
using namespace std;
//定義向量的輸出函式
templatevoid output(vectorvec)
{ for(unsigned i=0;ihp(a,9);
hp.insertvalue(-1);
hp.insertvalue(4);
hp.insertvalue(0);
hp.insertvalue(11);
cout<
cout<
cout<
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...
排序演算法 堆排序
花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...
排序演算法 堆排序
由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...