完全二叉樹之所以用數組的方式存在,在於他的一個特性 若子節點爲i,則父節點爲(i-1)/2,注意c++特性,該結果肯定是個整數。
若父節點爲j,則子節點必爲2*j+1;則在數組裏面可以非常方便的通過下標去獲取。
建堆的核心思想:
堆在index的值爲heap[index],然後其兩個孩子的值邊可求得,左孩子爲heap[index*2+1],右孩子爲heap[index*2+2]。
首先比較左邊孩子與右邊孩子,獲取較小值的孩子,然後讓heap[index]與值較小的孩子進行比較。若值小則交換值,並且移動index到值較小孩子的位置,否則退出調整。
下面看代碼,有註釋:
#pragma once template<class T> class JBMinHeap { private: //申請堆空間 T *_minHeap = NULL; int _index,_maxSize; public: JBMinHeap(int maxSize) { _maxSize = maxSize; _minHeap = new T[_maxSize]; _index = -1; } JBMinHeap(JBMinHeap &h) { _index = h._index; _maxSize = h._maxSize; _minHeap = new T[_maxSize]; for (int i = 0;i<_maxSize) { *_minHeap[i] = *h._minHeap[i]; } } ~JBMinHeap() { delete[]_minHeap; } //獲取整個最小堆的頭部指針 T * getMinHeap() { return _minHeap; } //判斷堆是不是空的 bool isEmpty() { return _index == -1; } bool add(T x) { if (isFull()) { return false; } _index++; _minHeap[_index] = x; return true; } bool isFull() { return _index == _maxSize; } //堆進行向下調整 void adjustDown(int index); //隊進行向上調整 void adjustUp(int index); //建堆運算 void createMinHeap() { if (isEmpty()) { return; } for (int i = (_index-1)/2;i >-1;i--) {//直接從倒數第二層 逐層向下調整 adjustDown(i); } } }; template<class T> void JBMinHeap<T>::adjustDown(int index) { if (isEmpty()) { return; } while (index<_index) { T temp = _minHeap[index];//將當前索引的位置的值保存下來 int oneC = 2 * index + 1;//獲取到兩個孩子的位置 int twoC = 2 * index + 2; if (oneC == _index) {//若第一個孩子是整個堆最後一個位置 則直接執行交換操作並結束執行 _minHeap[index] = _minHeap[oneC]; _minHeap[oneC] = temp; return; } if (twoC >_index) {//如果第二個孩子的索引位置越界 結束執行 return; } if (_minHeap[oneC] <= _minHeap[twoC]) {//正常情況的數據交互執行 if (temp > _minHeap[oneC]) { _minHeap[index] = _minHeap[oneC]; _minHeap[oneC] = temp; index = oneC; } else {//如果該處索引值已經是比兩個孩子小 則結束循環 index = _index; } } else { if (temp > _minHeap[twoC]) { _minHeap[index] = _minHeap[twoC]; _minHeap[twoC] = temp; index = twoC; } else { index = _index; } } } } template<class T> void JBMinHeap<T>::adjustUp(int index) { if (index > _index) {//大於堆的最大值直接return return; } while (index>-1) { T temp = _minHeap[index]; int father = (index - 1) / 2; if (father >= 0) {//若果索引沒有出界就執行想要的操作 if (temp < _minHeap[father]) { _minHeap[index] = _minHeap[father]; _minHeap[father] = temp; index=father; } else {//若果已經是比父親大 則直接結束循環 index = -1; } } else//出界就結束循環 { index = -1; } } }
主程序:
#include "stdafx.h" #include"stdlib.h" #include"JBQueue.h" #include"JBStack.h" #include"JBBinaryTree.h" #include"JBMinHeap.h" int main() { { JBMinHeap<int> jb(10); jb.add(20); jb.add(18); jb.add(19); jb.add(13); jb.add(42); jb.add(5); jb.createMinHeap(); int *p=jb.getMinHeap(); printf("整理爲最小堆:\n"); for (int i = 0;i < 6;i++) { printf("%d\n",p[i]); } } system("pause"); return 0; }