在數據結構裏,堆是一類很重要的結構。堆結構是一組數組對象,咱們能夠把它看成是一顆徹底二叉樹。ios
最大堆:堆裏每個父親節點大於它的子女節點。編程
最小堆:堆裏每個父親節點小於它的子女節點。數組
如圖就是一個最大堆:
數據結構
實現代碼時個人測試序列是:int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };ide
咱們把它的圖畫出來,便於分析。函數
咱們來實現如何將一個數組中的序列轉變爲最大堆。測試
若咱們知道最大堆的代碼後,只需將代碼稍微修改一下就能夠變成最小堆的代碼。或者,咱們能夠用仿函數來提升代碼的複用性。
spa
實現代碼以下:對象
創建頭文件heap.hpp
get
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; #include<assert.h> #include<vector> template <class T> class Heap { public: Heap() :_a(NULL) {} //構造堆:先把各個元素接收到,再根據堆的特色將元素調整 Heap(const T* array, size_t size) { _a.reserve(size); for (size_t i = 0; i < size; i++) { _a.push_back(array[i]); } //建堆 int Size = size; for (int j = (_a.size() - 2) / 2; j>=0; j --) { _AdjustDown(j, Size); } } //拷貝構造 Heap(const vector<T>& vec) :_a(NULL) { _a.reserve(vec.size()); for (size_t i = 0; i < size; i++) { _a.push_back(vec[i]); } } //插入一個元素x:先插入到順序表中,再根據具體元素大小向上調整肯定插入元素的位置 void Push(const T& x) { _a.push_back(x); _AdjustUp(_a.size() - 1); } //刪除根節點 void Pop() { size_t size = _a.size(); assert(size > 0);//防護式編程,肯定是否能夠刪除元素 swap(_a[0], _a[size - 1]);//若直接刪除堆的根節點,則會使堆結構紊亂 _a.pop_back();//將根節點與堆的最後一個節點交換位置,此時再對元素刪除,以及將其調整於合適位置 size = _a.size(); _AdjustDown(0,size); } //訪問堆的根節點 T& GetTop() { size_t size = _a.size(); assert(size > 0); return _a[0]; } //將根節點向下調整 void _AdjustDown(size_t parent,size_t size) { size_t child = 2 * parent + 1; while (child<size) { if (child+1 < size && _a[child] < _a[child + 1]) { child++; } if (_a[child] > _a[parent]) { swap(_a[child], _a[parent]); parent = child; child = 2 * parent + 1; } else { break; } } } //向上調整 void _AdjustUp(int child) { //不管插節點後爲左子樹仍是右子樹,均可用(child-2)/2計算出此時父節點的下標 int parent = (child - 1) / 2; int size = _a.size();//size用int,若用size_t循環條件且爲>=0則死循環 while (child>0)//當child=0,說明此時已經到根節點位置,無需繼續上調 { //向上調整時,無需看左右節點哪一個值大,只須要看是否父節點<根節點 if (_a[child]>_a[parent]) { swap(_a[child], _a[parent]); child = parent; parent = (child-1)/2; } else { break; } } } bool Empty() { size_t size = _a.size(); assert(size >= 0); return size == 0; } size_t Size() { size_t size = _a.size(); assert(size >= 0); return size; } void PrintHeap() { cout << "堆的序列爲:" << endl; for (int i = 0; i < Size(); i++) { cout << _a[i] << " "; } cout << endl; } private: vector<T> _a; };
創建源文件heap.cpp
#define _CRT_SECURE_NO_WARNINGS 1 #include "heap.hpp" void Test() { int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 }; Heap<int> h1(a, sizeof(a) / sizeof(a[0])); Heap<int> h2(h1); cout<<h1.GetTop()<<endl; cout << h1.Size() << endl; h1.Push(20); cout << h1.GetTop() << endl; h1.Pop(); cout << h1.Size() << endl; } int main() { Test(); system("pause"); return 0; }
關於size(),GetTop()等函數咱們能夠經過測試函數Test()寫出適當的測試用例來測試。