哈夫曼树这里就不介绍了。
这里主要是想处理一下自己写构造哈夫曼树时遇到的问题。
一开始,我是建了一个存结构体指针的优先队列,以权值为标准从小到大排序,然后选最小和次小节点组成父节点。但是运行后权值的排序是乱的。既不是从小到大也不是从大到小。在找了许多篇博客才终于明白,指针容器是不推荐的。它会有很多问题。
但是,我们需要用到优先队列进行O(lgn)的插入,又要存放节点的指针。这该如何操作呢?
我们可以建一个节点类型的优先队列,节点里面加一个指针:node *self. 表示指向自己的指针。这样我们就可以通过节点访问到节点指针了。对于每个节点x,我们先用指针new出来,然后进行各种初始化,最后我们push(*x)即可。
下面上代码:
#include <bits/stdc++.h>
using namespace std;
struct node{
int val; //记录权值
node *self = NULL; //存自己的节点
node *left = NULL; //左子节点
node *right = NULL; //右子节点
bool operator < (const node &b)const{
return val > b.val;
}
};
vector<int> a;
priority_queue<node> Q;
node rt; //哈夫曼树根节点
int ans;
void build()
{
while(!Q.empty())
{
node n1 = Q.top(); //选最小
Q.pop();
if(!Q.empty())
{
node n2 = Q.top(); //选次小
Q.pop();
cout<<n1.val<<" "<<n2.val<<endl;
node *n = new node; //最小和次小相加组成其父结点
n->val = n1.val + n2.val; //初始化父结点
n->self = n;
n->left = n1.self;
n->right = n2.self;
Q.push(*n);
ans += n->val; //顺便计算WPL(除叶子节点的所有结点权值总和)
}
else
{
rt = n1; //最后剩下的为根节点
}
}
}
void pre(node *rt) //先序遍历
{
if(rt)
{
cout<<rt->val<<" ";
pre(rt->left);
pre(rt->right);
}
}
int main()
{
int n, x;
cin>>n;
for(int i = 0;i < n;i++)
{
cin>>x;
a.push_back(x);
node *s = new node; //建叶子节点
s->val = x, s->self = s;
Q.push(*s);
}
build();
cout<<"WPL:"<<ans<<endl;
cout<<"先序遍历:"<<endl;
pre(rt.self);
return 0;
}