C++优先队列重载运算符,存入结构体指针后输出异常

如图所示

img

在写小算法,哈夫曼树编码解码。
我尝试着在建树的步骤中使用优先队列,但是在运算符重载后,我发现了一个问题。
运算符重载的是结构体类型,但是优先队列中存储的是指针,在向优先队列中添加了结点后输出权值,输出的却是地址。

随后写了个小demo实验一番,如图所示,结果更奇怪了,在存入三个指针后,输出了两个地址和一个值
这是为什么?

小demo代码


#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct demo {
    int number;
    
    bool operator < (const demo &a) const {
        return number<a.number;
    }
    bool operator > (const demo &a) const {
        return number>a.number;
    }
    
    //Init
    demo() {
        number = 0;
    }
    demo(int num) {
        number = num;
    }
};

int main() {
    //优先队列 
    priority_queue<demo*, vector<demo*>, greater<demo*> > aaa;
    
    
    for(int u = 1; u<= 3; u++) {
        demo* ddd = new demo(u);
        aaa.push(ddd);
        delete ddd;
    }
    
    //输出所有 
    while(!aaa.empty()) {
        cout << aaa.top()->number << endl;aaa.pop();
    }
}

问题已解决,修改后代码为

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct demo {
    int number;
    bool operator < (const demo &a) const {    return number<a.number;}
    bool operator > (const demo &a) const { return number>a.number;}
    //Init
    demo() { number = 0;}
    demo(int num) {    number = num;}
};

int main() {
    //优先队列 
    priority_queue<demo*, vector<demo*>, greater<demo*> > aaa;
    demo* ddd = NULL;    
    for(int u = 1; u<= 3; u++) {
        ddd = new demo(u);
        aaa.push(ddd);
    }
    
    //输出所有 
    while(!aaa.empty()) {
        cout << aaa.top()->number << " ";aaa.pop();
    }
}

demo代码运行过吗?demo类的所有成员都是私有的?
aaa.push(ddd); 这里push存储的都是指针而已,你接着delete ddd就完蛋了。vector存储的全成了野指针了啊

push 了 后 把 delete 那句删掉

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7768066
  • 这篇博客你也可以参考下:纯c代码 输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组
  • 除此之外, 这篇博客: 回溯法与分支限界法的总结中的 在当前节点(扩展节点)处,先生成其所有的子节点(分支),然后再从当前的活节点(当前节点的子节点)表中选择下一个扩展节点。为了有效地选择下一个扩展节点,加速搜索的进程,在每一个活节点处,计算一个函数值(限界),并根据函数值,从当前活节点表中选择一个最有利的节点作为扩展节点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。分支限界法解决了大量离散最优化的问题。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 编写回溯算法代码时,要先考虑这个问题是一个什么搜索树,然后套用那个搜索树模板就行了。(例如:子集树就是:判断是否满足约束条件——计算、x[i]=1——递归左子树——归还——x[i]=0、递归右子树(注意限界思想))
    (例如:排列树就是:循环——判断是否满足约束条件——交换——计算——递归(注意限界思想)——归还)
    当然具体算法要具体分析
    还要注意及时更新解和存储解,别忘了进入右子树、循环结束前,要将你算的、交换过的东西,要归还回去。注意到达叶结点干什么,没有到达怎么做

    而分支限界算法的代码编写,首先编写三个类:活结点类、活结点属性类、入队类。然后选择好什么样的队列方式。一定要考虑好属性,然后什么时候添加结点、以及出队、和存储最优解

    两个算法编写,还要注意限界函数的设置,怎么设计一个好的代价函数可以裁掉更多的空间。这就是两个算法的优化思想。

    当然最重要的还要考虑好约束条件。

    具体逻辑代码还是多写多练。多去总结。这里也就只讲个大体思路。

  • 您还可以看一下 李月喜老师的企业微信开发自建内部应用开发篇课程中的 开发文档如何阅读,如何寻求帮助,如何找到同行小节, 巩固相关知识点