/*本题看似简单,实现哈夫曼编码书即可,但是还是折腾近三个小时,需要注意以下三点:
priority_queue自定义结构体的写法,结构体中定义友元函数,或者重载<,但是一定要写上两个const和引用
由于结构体存在指针,出队列的元素应给其分配永久存储空间new,而不是将指针指向局部变量
由于多次输入输出,所以,将特殊类型如结构体,队列,节点都定义为局部变量,每次循环重新定义即可
*/
struct node{
//这个题目被卡主的地方就是优先级队列中结构体的写法,const和引用都得写,
char c;
int f;
node* lchild;
node* rchild;
node(char cc='a',int ff='0',node* l=NULL,node* r=NULL):c(cc),f(ff),lchild(l),rchild(r){}
//这里要加上const 和引用,否则报错,这两条是priority-queue的特殊规则了吧,暂时先不深究了,先记住。结构体优先级队列必备知识
//node(const node& b):c(b.c),f(b.f),lchild(b.lchild),rchild(b.rchild){}
//这里需要注意写法,friend不能省,不能只写引用,要么引用和const都不写,要么都写
friend bool operator<(const node& a,const node& b){
return a.f>b.f||(a.f==b.f&&a.c>b.c);
}
//或者时下面这种写法,两个const不能省
/*bool operator < (const node& b)const{
return f>b.f||(f==b.f&&c>b.c);
}*/
};
void travel(node* root,string s){
if(root==NULL)return;
travel(root->lchild,s+"0");
if(root->lchild==NULL&&root->rchild==NULL){
cout<<root->c<<":"<<s<<endl;
}
travel(root->rchild,s+"1");
}
int main(){
freopen("d:\\input.txt","r",stdin);
int n;
char c[2];int m;
while(1){
//这里要注意,把特殊变量每次需要清空的定义为局部变量,就可以自动清空了
node tt;
priority_queue<node> pq;
string s;
if(scanf("%d",&n)==EOF)break;
for(int i=0;i<n;i++){
scanf("%s %d",c,&m);
tt.c=c[0];tt.f=m;
pq.push(tt);
}
node* nodet;
while(pq.size()!=1){
//原来第二次遇到的问题在这里,notet的元素指向a,b的指针,而在下一次循环中,a,b的值发生了变化,指针的指向也变化,原因在于指针指向的是一个临时变量
//出队的元素不再入队,应建立永久变量
node* a=new node(pq.top());
pq.pop();
node* b=new node(pq.top());
pq.pop();
//千万注意,这里的指针不能指向临时变量
nodet=new node(a->c,a->f+b->f,a,b);
pq.push(*nodet);
}
tt=pq.top();
pq.pop();
travel(&tt,s);
}
return 0;
}