注意vector保存的内存地址可能会变,所以如果用vector来存储所有节点的话,需要先resize好容器,保证期间不进行节点的增减。multiset是允许关键字重复的容器
#include<vector>
#include<iostream>
#include<string>
#include<set>
using namespace std;
struct node {
string data;
int w;//权值或概率
string ma;
node *l, *r;
int flag;
node() { l = r = NULL;ma = "";flag = 0; }
bool operator<(const node b) const {
return w < b.w;
}
};
multiset<node> all;
vector<node> resault;//最终的所有节点
int N;
void dfs(node *&root)//赫尔曼编码
{
if (root->l) {
root->l->ma = root->ma + "0";dfs(root->l);
}
if (root->r) {
root->r->ma = root->ma + "1";dfs(root->r);
}
}
int main()
{
int cnt = 0;
cout << "请输入节点的个数" << endl;
cin >> N;
resault.resize(2 * N - 1);
cout<<"请依次输入各节点的名字和权值"<<endl;
while (N--)
{
node tem;
cin >> tem.data >> tem.w;
tem.flag = 1;
all.insert(tem);
}
while (all.size() != 1)//选2个最小的到resault中,并创建一个最小合并的节点到all
{
node tem;
auto it2 = all.begin(), it = all.begin();
it2++;
resault[cnt++] = *it;
resault[cnt++] = *it2;
tem.l = &resault[cnt - 2];tem.r = &resault[cnt - 1];
tem.data = "(" + tem.l->data + "+" + tem.r->data + ")";
tem.w = tem.l->w + tem.r->w;
it2++;
all.erase(it, it2);
all.insert(tem);
/*for (auto x : all)
cout << x.data << " ";
cout << endl;*/
}
resault[cnt++] = *all.begin();
//遍历,求所求//比如赫尔曼码
node *root = &resault[resault.size() - 1];
dfs(root);
for (auto x : resault)
if (x.flag == 1) cout << x.data << " " << x.ma << endl;
}