C++实现最大堆最小堆
目錄
堆和棧的區別
最大堆與最小堆
最大堆的操作
最大堆的插入操作
最大堆的彈出操作
最大堆的C++代碼實現
最小堆概念
最小堆的插入操作
最小堆的彈出操作
最小堆的C++代碼實現
最大堆最小堆的應用
1.priority_queue
2. STL 堆操作
堆和棧的區別
一、堆棧空間分配區別:
1、棧(操作系統):由操作系統自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧;
2、堆(操作系統): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似于鏈表。
二、堆棧緩存方式區別:
1、棧使用的是一級緩存, 他們通常都是被調用時處于存儲空間中,調用完畢立即釋放;
2、堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定(并不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。
三、堆棧數據結構區別:
堆(數據結構):堆可以被看成是一棵樹,如:堆排序;
棧(數據結構):一種先進后出的數據結構。
最大堆與最小堆
最大堆:根結點的鍵值是所有堆結點鍵值中最大者,且每個結點的值都比其孩子的值大。
最小堆:根結點的鍵值是所有堆結點鍵值中最小者,且每個結點的值都比其孩子的值小。
最小堆和最大堆的增刪改相似,其實就是把算法中的大于改為小于,把小于改為大于。
最大堆的操作
在生成最大堆時,我們可以采取一次次遍歷整棵樹找到最大的結點放到相應的位置中。但是這種方法有個不好的地方,就是每個結點都要重復比較多次。
所以我們可以換一種思考的順序,從下往上進行比較。先找到最后一個有子結點的結點,先讓他的兩個子結點進行比較,找到大的值再和父結點的值進行比較。如果父結點的值小,則子結點和父結點進行交換,交換之后再往下比較。然后一步步遞歸上去,知道所在結點的位置是0號位置跳出。這樣就可以有效地減少比較所用到的時間。
但是每一次交換都要重復三步:temp = heap[i]; heap[i] = heap[j]; heap[j] = temp;
當樹的結構比較大的時候,就會浪費很多時間。所以我們可以先把父結點的值存到temp中跟子結點比較,如果子結點大的話就把子結點的值賦值給父結點,再往下比較,最后才把temp的值存到相應的位置。
最大堆的插入操作
每當插入一個元素,將元素插入到容器(數組)尾部,然后執行迭代的上升操作,將插入的元素與其父節點比較,若比父節點大則交換,然后再與交換后節點的父節點相互比較交換,直到放置到合適位置。(最壞遞歸到根節點終止迭代)
最大堆的彈出操作
彈出最大值(即數組首地址元素 a[0])。先交換交換堆頂與堆末,再彈出堆末(最大值),然后再將現堆頂元素執行迭代的下降操作,若其子節點存在與其子節點比較,若比子節點小則交換,然后再與交換后的子節點相互比較交換,直到放置在合適位置。(最壞遞歸到葉子節點)
最大堆的C++代碼實現
#include <iostream> #include<vector> using namespace std;#define ElementType int//構造大頂堆類 class MaxHeap { private:vector<ElementType> a; public://構造大頂堆MaxHeap(ElementType elements[], int number){for (int i = 0; i < number; i++){a.push_back(elements[i]);}for (int i = a.size() / 2 - 1; i >= 0; i--){down(i);}}//交換i,j下標對應元素void swap(int i, int j){ElementType temp = a[i];a[i] = a[j];a[j] = temp;}//上升操作void up(int i){int fa = (i - 1) / 2;//f表示父節點下標if (i > 0 && a[i] > a[fa]){swap(i, fa);up(fa);//如果一直比父節點大,遞歸到根節點(下標0)}}//插入點void push(ElementType p){a.push_back(p);up(a.size() - 1);//上升操作 直到合適位置}//下降操作void down(int i){int son = 2 * i + 1;//son表示子節點下標if (son < a.size()){if (son + 1 < a.size() && a[son] < a[son + 1]){son++; //取值兩個子節點 值更大的節點下標}//若子節點大,交換if (a[i] < a[son]){swap(i, son);}down(son);//遞歸調用,直到葉子節點}}//彈出堆頂節點(最大)ElementType pop(){ElementType result = a[0];swap(0, a.size() - 1);//交換堆頂與堆末a.pop_back();//彈出down(0);//再將原來的最末元素(現在的堆頂元素)下降操作,使之到合適位置return result;}//輸出堆(順序輸出)void show(){for (int i = 0; i < a.size(); i++) {cout << " " << a[i];}cout << endl;} }; int main(void) {int a[] = { 13,43,84,96,22,65,70,47 };MaxHeap* m = new MaxHeap(a, 8);//測試cout << "顯示當前最大堆:" << endl;m->show();cout << "彈出最大堆頂的元素:" << m->pop() << endl;cout << "顯示當前最大堆:" << endl;m->show();cout << "插入一個節點90:" << endl;m->push(90);cout << "顯示當前最大堆:" << endl;m->show();return 0; }最小堆概念
最小堆,是一種經過排序的完全二叉樹,其中任一非終端節點的數據值均不大于其左子節點和右子節點的值。堆內的所有數據中最小的元素始終在堆頂,而增刪一個元素而動態維護最小堆性質的時間復雜度僅為 O(logN)
最小堆的插入操作
每當插入一個元素,將元素插入到容器(數組)尾部,然后執行迭代的上升操作,將插入的元素與其父節點比較,若比父節點小則交換,然后再與交換后節點的父節點相互比較交換,直到放置到合適位置。(最壞遞歸到根節點終止迭代)
最小堆的彈出操作
彈出最小值(即數組首地址元素 a[0])。先交換交換堆頂與堆末,再彈出堆末(最小值),然后再將現堆頂元素執行迭代的下降操作,若其子節點存在與其子節點比較,若比子節點小則交換,然后再與交換后的子節點相互比較交換,直到放置在合適位置。(最壞遞歸到葉子節點)
最小堆的C++代碼實現
#include <iostream> #include<vector> using namespace std;#define ElementType intclass MinHeap { private:vector<ElementType> a; public://構造小頂堆MinHeap(ElementType elements[], int number){for (int i = 0; i < number; i++){a.push_back(elements[i]);}for (int i = a.size() / 2 - 1; i >= 0; i--){down(i);}}//交換i,j下標對應元素void swap(int i, int j){ElementType temp = a[i];a[i] = a[j];a[j] = temp;}//上升操作void up(int i){int fa = (i - 1) / 2;//f表示父節點下標if (i > 0 && a[i] < a[fa]){swap(i, fa);up(fa);//如果一直比父節點小,遞歸到根節點(下標0)}}//插入點void push(ElementType p){a.push_back(p);up(a.size() - 1);//上升操作 直到合適位置}//下降操作void down(int i){int son = 2*i + 1;//son表示子節點下標if (son < a.size()){if (son + 1 < a.size() && a[son] > a[son + 1]){son++; //取值兩個子節點 值更小的節點下標}//若子節點小,交換if (a[i] > a[son]){swap(i, son);}down(son);//遞歸調用,直到葉子節點}}//彈出堆頂節點(最小)ElementType pop(){ElementType result = a[0];swap(0, a.size() - 1);//交換堆頂與堆末a.pop_back();//彈出down(0);//再將原來的最末元素(現在的堆頂元素)下降操作,使之到合適位置return result;}//輸出堆(順序輸出)void show(){for (int i = 0; i < a.size(); i++){cout << " " << a[i];}cout << endl;} };int main(void) {int a[] = { 13, 43, 84, 96, 22, 65, 70, 47 };MinHeap* m = new MinHeap(a, 8);//測試cout << "顯示當前最小堆:" << endl;m->show();cout << "彈出最小堆頂的元素:" << m->pop() << endl;cout << "顯示當前最小堆:" << endl;m->show();cout << "插入一個節點30:" << endl;m->push(30);cout << "顯示當前最小堆:" << endl;m->show();return 0; }最大堆最小堆的應用
1.priority_queue
2. STL 堆操作
頭文件是#include <algorithm>
一般用到這四個:make_heap()、pop_heap()、push_heap()、sort_heap();
總結
以上是生活随笔為你收集整理的C++实现最大堆最小堆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 丁腈橡胶自然老化时间_东莞元耀:解析抗U
- 下一篇: 详解C++移动语义std::move()