优先队列存储自定义类型对象的指针
一开始我想用优先队列来实现构造哈夫曼树,并以指针方式存储每个结点的左右儿子的地址
很自然的想到如下的代码
#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;
}