如priority_queue、set的模板类中的值不应动态更改

用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;
}
/*
输出如下
4
3
2
1
0
*/
  • 更改其中的一个值
// ……上略
ans[3] = 8;
while (!queue.empty()) {
    cout << queue.top() << endl;
    queue.pop();
}  
// ……下略
/*
输出如下
4
8
2
1
0
*/
  • 更改后重新插入一个值
  • 这里发现,即使重新插入一个值,错误的排序仅仅局部被纠正
// ……上略
ans[3] = 8;
queue.push(Val(5));
while (!queue.empty()) {
    cout << queue.top() << endl;
    queue.pop();
}  
// ……下略
/*
输出如下
5
8
4
2
1
0
*/
  • 如果改一个另一个值
  • 又突然可以排序了。
// ……上略
ans[3] = -5;
while (!queue.empty()) {
    cout << queue.top() << endl;
    queue.pop();
}  
// ……下略
/*
输出如下
4
2
1
0
-5
*/

使用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;
}
/*
输出如下
0 1 2 3 4
0 1 2 8 4
0 1 2 5 8 4
*/

总结

  • priority_queue其实是维护了一个大顶堆
    • 而堆的特性决定了,堆的操作都是在堆顶进行的。
    • 所以直接更改中间的值会引起复杂的错误。
  • set的结构应该是红黑树。理论上可以实现,比如更新前先erase()这个值,然后换了后插入。然后不过也不能动态更新。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值