用priority_queue时遇到的坑
使用的priority_queue
- 就是如下代码priority_queue实际保存的是一个索引对象,但排序使用的是索引的值。
- 一个疑问就是当索引对象不变,索引的值变化时,相应的堆会重排序吗?
int ans[] = {0, 1, 2, 3, 4, 5, 7, 8};
struct Val{
int val;
Val(int val) : val(val) {}
};
bool operator<(const Val &A, const Val &B) {
return ans[A.val] < ans[B.val];
}
ostream &operator<<(ostream &OS, const Val &Val){
OS << ans[Val.val];
return OS;
}
int main()
{
priority_queue<Val> queue;
for(int i = 0; i < 5; ++i) {
queue.push(Val(i));
}
while (!queue.empty()) {
cout << queue.top() << endl;
queue.pop();
}
return 0;
}
ans[3] = 8;
while (!queue.empty()) {
cout << queue.top() << endl;
queue.pop();
}
- 更改后重新插入一个值
- 这里发现,即使重新插入一个值,错误的排序仅仅局部被纠正
ans[3] = 8;
queue.push(Val(5));
while (!queue.empty()) {
cout << queue.top() << endl;
queue.pop();
}
ans[3] = -5;
while (!queue.empty()) {
cout << queue.top() << endl;
queue.pop();
}
使用set
- set不仅自己不会排序,而且把新加入的序列顺序也弄乱了
int ans[] = {0, 1, 2, 3, 4, 5, 7, 8};
struct Val{
int val;
Val(int val) : val(val) {}
};
bool operator<(const Val &A, const Val &B) {
return ans[A.val] < ans[B.val];
}
ostream &operator<<(ostream &OS, const Val &Val){
OS << ans[Val.val];
return OS;
}
int main()
{
set<Val> queue;
for(int i = 0; i < 5; ++i) {
queue.insert(Val(i));
}
for(set<Val>::iterator it = queue.begin(); it != queue.end(); ++it){
cout << *it << ' ';
}
cout << endl;
ans[3] = 8;
for(set<Val>::iterator it = queue.begin(); it != queue.end(); ++it){
cout << *it << ' ';
}
cout << endl;
queue.insert(Val(5));
for(set<Val>::iterator it = queue.begin(); it != queue.end(); ++it){
cout << *it << ' ';
}
cout << endl;
return 0;
}
总结
- priority_queue其实是维护了一个大顶堆
- 而堆的特性决定了,堆的操作都是在堆顶进行的。
- 所以直接更改中间的值会引起复杂的错误。
- set的结构应该是红黑树。理论上可以实现,比如更新前先erase()这个值,然后换了后插入。然后不过也不能动态更新。