您正在寻找的是堆数据结构。堆是满足以下条件的二叉树:
- 每个节点都有一个父节点、一个左子节点和一个右子节点(它们可能是
NULL
)
- 每个节点都有一个键和一个优先级
- 如果
p
是 的父级u
,则p.priority
<u.priority
了解所有这些,您可以有效地实施insert(key, priority)
操作remove()
。更具体地说,每个提到的操作的复杂度为O(log N)
,其中 N 是优先级队列的大小。有关堆数据结构的更多信息,请参见 Wikipedia:http://en.wikipedia.org/wiki/Heap_(data_structure)。下面我发布了一些我写的代码(我没有对它进行很多测试,但我认为它有效)。
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
#define MAXN 100005
#define L(n) (2*n)
#define R(n) (2*n+1)
#define P(n) (int)(n/2)
struct Node {
int p;
string s;
void swap(Node &other) {
Node tmp = (Node){p, s};
p = other.p, s = other.s;
other.p = tmp.p, other.s = tmp.s;
}
};
template<typename Key, typename Priority>
struct PriorityQueue {
private:
vector<pair<Key, Priority> > pq;
int size;
void bubble_up(int u) {
while(P(u)) {
if(pq[P(u)].second > pq[u].second) {
swap(pq[u], pq[P(u)]);
u = P(u);
} else break;
}
}
void bubble_down(int u) {
while(L(u) <= size) {
int pp = min(pq[u].second, pq[L(u)].second);
if(R(u) <= size) pp = min(pp, pq[R(u)].second);
if(pp == pq[u].second) break;
else if(pp == pq[L(u)].second) {
swap(pq[u], pq[L(u)]);
u = L(u);
} else {
swap(pq[u], pq[R(u)]);
u = R(u);
}
}
}
public:
PriorityQueue() : pq(1), size(0) {}
void add(Key key, Priority priority) {
pq.push_back(make_pair(key, priority));
bubble_up(++size);
}
Key remove() {
Key ret = pq[1].first;
swap(pq[1], pq[size--]);
pq.pop_back();
bubble_down(1);
return ret;
}
};
int main() {
PriorityQueue<string, int> Q;
Q.add("X", 10);
Q.add("Y", 1);
Q.add("Z", 3);
Q.add("K", 7);
cout << Q.remove() << endl;
cout << Q.remove() << endl;
cout << Q.remove() << endl;
cout << Q.remove() << endl;
return 0;
}
编辑:我将函数add()
和remove()
放入一个名为PriorityQueue
. 我还扩展了结构以接受其他类型的键和优先级。我希望它有帮助:)