所有的數據結構書中都有關於堆的詳細介紹,向堆中插入、刪除元素時間復雜度都是O(lgN),N為堆中元素的個數,而獲取最小key值(小根堆)的復雜度為O(1)。
堆是一個完全二叉樹,基本存儲方式是一個數組。
優先隊列是一種比較常用的結構,雖然被稱為隊列,但卻不是隊列。
- C++ STL默認的priority_queue是將優先級最大的放在隊列最前面,也即是最大堆。那么如何實現最小堆呢?
假設有如下一個struct:
struct Node { int value; int idx; Node (int v, int i): value(v), idx(i) {} friend bool operator < (const struct Node &n1, const struct Node &n2) ; }; inline bool operator < (const struct Node &n1, const struct Node &n2) { return n1.value < n2.value; } priority_queue<Node> pq; // 此時pq為最大堆
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
如果需要最大堆,則需要如下實現:
struct Node { int value; int idx; Node (int v, int i): value(v), idx(i) {} friend bool operator > (const struct Node &n1, const struct Node &n2) ; }; inline bool operator > (const struct Node &n1, const struct Node &n2) { return n1.value > n2.value; } priority_queue<Node, vector<Node>, greater<Node> > pq; // 此時greater會調用 > 方法來確認Node的順序,此時pq是最小堆
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
其他解決
當然,還有些比較小的較為hack的手段進行。比如要構造一個int類型的最小堆:
priority_queue<int> pq; // pq.push( -1 * v1) ; // pq.push( -1 * v2) ; // pq.push( -1 * v3) ; // 分別是插入v1, v2, v3變量的相反數,那么pq其實也就變相成為了最小堆,只是每次從pq取值后,要再次乘以-1即可
- 1
- 2
- 3
- 4
此外,再貼一份網上的某
#include <iostream> #include <queue> using namespace std; struct node{ int idx; int key; node(int a=0, int b=0):idx(a), key(b){} }; struct cmp{ bool operator()(node a, node b){ return a.key > b.key; } }; int main(){ priority_queue<node, vector<node>, cmp> q; int i; for(i=0;i<10;++i){ q.push(node(i, i)); } while(!q.empty()){ cout<<q.top().key<<endl; q.pop(); } return 0; }