1.定義
在一棵樹中,每個節點都大於(小於)它的左右孩子,這棵樹叫做大根樹(小根數)。一個大根堆就是一棵大根樹,也是一棵完全二叉樹。
如圖所示大根樹,這個樹每個節點都大於它的子節點(除葉子節點以外)。
2.存儲方式
採用一維數組存儲大根堆的每個節點最爲方便。大根堆也是一棵完全二叉樹,使用數組存儲效率也很高。上述大根堆存儲到數組後,如下圖所示。
採用前序遍歷的方法存儲在數組中。
定義代碼如下:
class maxHeap {
public:
maxHeap(int cap);
~maxHeap() { delete[]heap; };
int getSize() const { return heapSize; };
void pop();
void push(const int);
void print();
private:
int *heap; //1維數組
int heapSize; //節點個數
int capacity; //容量
};
maxHeap::maxHeap(int cap)
{
if (cap < 1)
cout << "初始化大小必須大於10" << endl;
capacity = cap;
heapSize = 0;
heap = new int[cap];
for (int i = 0; i < cap; i++)
heap[i] = 0;
}
3.大根堆插入
3.1如果插入新節點:2
插入後,依然是大根堆,所以直接插入即可。
3.2 如果插入新節點:20
插入20後,因爲9小於20,所以不符合大根堆。需要將節點9下移或將節點20上移,構成一個新的大根堆。
插入代碼如下:
void maxHeap::push(const int newElement)
{
//擴大容量
if (heapSize >= capacity - 1)
{
int *temp = new int[capacity * 2];
for (int i = 0; i < capacity * 2; i++)
temp[i] = 0;
copy(heap, heap + capacity, temp);
delete[]heap;
heap = temp;
}
//插入到最末尾的葉子節點上
int node = ++heapSize;
//插入後,遍歷一遍檢查是否符合大根堆
//注:節點存放從數組heap[1]開始存放
//這樣任意一個非根節點的位置除以2,即爲當前節點的根節點的位置
while (node != 1 && heap[node / 2] < newElement)
{
heap[node] = heap[node / 2];
node /= 2;
}
heap[node] = newElement;
}
4.大根堆刪除
優先級隊列priority-queue使用的是大根堆實現的。大根堆的刪除就是刪除根節點。
4.1 步驟
刪除根節點,將末尾的節點移動到根節點
遍歷樹,維護成大根堆
實現代碼如下:
void maxHeap::pop()
{
if (heapSize <= 0)
{
cout << "沒有數據了" << endl;
return;
}
heap[1] = heap[heapSize];
heap[heapSize--] = 0;
int child = 1;
for (int i = 1; i * 2 + 1 <= heapSize; i++)
{
child *= 2;
//比較當前i節點左右孩子哪個比較大
if (child < heapSize && heap[child] < heap[child + 1])
child++;
//i節點與i節點最大的孩子互換
if (heap[i] < heap[child])
swap(heap[i], heap[child]);
}
}
5.結果
void maxHeap::print()
{
for (int i = 0; i < capacity; i++)
if (heap[i] != 0)
cout << heap[i] << ",";
cout << endl;
}
int main()
{
maxHeap heap(10);
heap.push(50);
heap.push(30);
heap.push(9);
heap.push(21);
heap.push(10);
heap.push(1);
heap.push(20);
heap.print();
heap.pop();
heap.print();
}
輸出結果: