• 优先队列存储自定义类型对象的指针


    一开始我想用优先队列来实现构造哈夫曼树,并以指针方式存储每个结点的左右儿子的地址
    很自然的想到如下的代码

    #include <iostream>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int MAX_N = 500;
    
    struct node {
        int v;
        node *le, *ri;
        node(int _v) : v(_v) { le = NULL, ri = NULL; }
        node(const node& x) { v = x.v, le = x.le, ri = x.ri; }
        bool operator < (const node& x) const {
            return v > x.v;
        }
    };
    
    priority_queue<node> q;
    
    void dfs(node *cur, int& ans, int lev) {
        if ((!cur->le) && (!cur->ri)) {
            ans += cur->v * lev;
            return;
        }
        if (cur->le)
            dfs(cur->le, ans, lev + 1);
        if (cur->ri)
            dfs(cur->ri, ans, lev + 1);
    }
    
    int main() {
    
        int n, ans = 0;
        cin >> n;
    
        node *root = NULL, *newnode = NULL;
        while (n--) {
            int tmp;
            cin >> tmp;
            newnode = new node(tmp);
            q.push(*newnode);
        }
    
        while (q.size() > 1) {
            node a = q.top();
            q.pop();
            node b = q.top();
            q.pop();
            newnode = new node(a.v + b.v);
            newnode->le = &a;
            newnode->ri = &b;
            q.push(*newnode);
            root = newnode;
        }
    
        q.pop();
    
        dfs(root, ans, 0);
    
        cout << ans << endl;
    
        return 0;
    }
    

    结果发现 \(RE\) 了,树的父子关系根本没有得到有效的保存
    调试与思考了很久以后发现,这是因为STL 容器中存放的元素是拷贝而不是引用

    对于内建类型(int float char等),容器的工作方式是纯粹的位拷贝。
    而当你向容器中添加一个自定义的对象(比如通过insert或push_back等),进入容器的是你指定的对象的拷贝。容器中存放的对象不是你给它们的那个对象,因为两个对象在内存中的位置不一样。
    此外,当你从容器中获取一个对象时,你所得到的对象也不是容器里的那个对象。取而代之的是容器中对象的拷贝。
    拷进去,拷出来。拷贝是STL的方式。

    那么为了解决这个问题,我们可以将对象的引用或者指针传入容器。而容器是不支持容纳对象的引用的
    因此我们采用传入对象的指针来解决这个问题,同时需要自定义优先队列中的比较器
    一般采取传入函数对象的方式,可以参考这个博客
    那么改正后的代码如下:

    #include <iostream>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int MAX_N = 500;
    
    struct node {
        int v;
        node *le, *ri;
        node(int _v) : v(_v) { le = NULL, ri = NULL; }
        node(const node& x) { v = x.v, le = x.le, ri = x.ri; }
    };
    
    struct cmp {   // 函数指针类型比较器
        bool operator()(const node* a, const node* b) const {
            return a->v > b->v;
        }
    };
    
    priority_queue<node*, vector<node*>, cmp > q;
    
    void dfs(node *cur, int& ans, int lev) {
        if ((!cur->le) && (!cur->ri)) {
            ans += cur->v * lev;
            return;
        }
        if (cur->le)
            dfs(cur->le, ans, lev + 1);
        if (cur->ri)
            dfs(cur->ri, ans, lev + 1);
    }
    
    int main() {
    
        int n, ans = 0;
        cin >> n;
    
        node *root = NULL, *newnode = NULL;
        while (n--) {
            int tmp;
            cin >> tmp;
            newnode = new node(tmp);
            q.push(newnode);
        }
    
        while (q.size() > 1) {
            node* a = q.top();
            q.pop();
            node* b = q.top();
            q.pop();
            newnode = new node(a->v + b->v);
            newnode->le = a;
            newnode->ri = b;
            q.push(newnode);
            root = newnode;
        }
    
        q.pop();
    
        dfs(root, ans, 0);
    
        cout << ans << endl;
    
        return 0;
    }
    
  • 相关阅读:
    有关SQL的查询问题
    Nginx学习笔记——搭建Linux +Nginx+PHP+Mariadb(MySql)开发环境
    查询组列表时直接显示需要的组内成员
    MySql联合查询Union
    jQuery使用ajax方法提交登陆信息时,遇到特殊字符&
    ubuntu下安装LNMP环境
    Ubuntu下安装VirtualBox增强插件
    开启Apache,允许外部访问
    Windows下安装Memcached
    关于xls的一点笔记
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/16320190.html
Copyright © 2020-2023  润新知