哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:
1.规定哈弗曼树的左子树编码为0,右子树编码为1;
2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;
3.创建的新节点所代表的字符与它的左孩子的字符相同;
4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。
3 a 10 b 5 c 8 4 a 1 b 1 c 1 d 1
a:0 b:10 c:11 a:00 b:01 c:10 d:11
我真是日了狗了。。。
一直想着出题人不会出n=0的情况把。一直也就没判断,wa了一夜。今天检查错误
一直没发现。就加上n=0 结果ac了。坑坑坑啊、、、
/* 8 a 5 b 29 c 7 d 8 e 14 f 23 g 3 h 11 */ #include <stdio.h> #include <queue> #include <string.h> #include <algorithm> using namespace std; struct node { char ch,code[100]; int val,left,right,fa,num; //结构体优先队列。对每个字符的权值排序 //先出权值比较小的,如果权值相等,出字符较小的 friend bool operator<(node a, node b) { if(a.val>b.val) return true; // if(a.val==b.val&&a.num>b.num) return true; if(a.val==b.val&&a.ch>b.ch) return true; return false; } }tree[200]; int N; //str字符串为存贮huffman编码 char str[100]; //对所有的huffman书按照序号排列 bool cmp(node a,node b) { return a.num<b.num; } //递归遍历huffman树,求每个字符的huffman编码 void dfs(int t,int q) { //t表示huffman树的节点个数 //当t<N的时候 就是字符 if(t<N) { //str[q]='\0',表示字符的结尾,便于后面的strcpy()函数 str[q]='\0'; strcpy(tree[t].code,str); //已经找到叶子节点,return结束这次递归 return ; }//if else { //如果存在左子树 if(tree[t].left!=-1) { str[q]='0'; q++; dfs(tree[t].left,q); //还原q q--; }//if //如果存在右子树 if(tree[t].right!=-1) { str[q]='1'; q++; dfs(tree[t].right,q); //还原q q--; }//if }//else }//dfs int main() { //构造一个优先队列 priority_queue<node>s; int n; while(scanf("%d",&n)!=EOF) { if(n==0) continue; //初始str字符串和huffman树 memset(str,0,sizeof(str)); memset(tree,0,sizeof(tree)); //输入n个字符和权值,将其放入优先队列 for(int i=0;i<n;i++) { getchar(); node temp; scanf("%c %d",&temp.ch,&temp.val); temp.left=temp.right=temp.fa=-1; temp.num=i; s.push(temp); } //N 全局变量 N=n; int t=0; //创建huffman树 //利用优先队列 每次选择权值最小的两个,然后将其结果在加入优先队列 // 将权值最小的两个 ,添加到树中 while(s.size()>1) { node temp1,temp2,temp3; temp1=s.top();s.pop(); temp2=s.top();s.pop(); temp3.val=temp1.val+temp2.val; temp3.ch=temp1.ch; temp3.left=temp1.num; temp3.right=temp2.num; temp3.fa=0; temp1.fa=temp2.fa=temp3.num=n++; tree[t++]=temp1; tree[t++]=temp2; s.push(temp3); } //优先队列里面剩下一个元素,它就是根节点,直接加到树中 tree[t++]=s.top(); s.pop(); //按照num序号排序 sort(tree,tree+t,cmp); //取消下面的注释,可以看到每个节点的序号,父节点,左子树,右子树,权值。 // for(int i=0;i<t;i++) // printf("%d %d %d %d %d\n",tree[i].num+1,tree[i].val,tree[i].fa+1,tree[i].left+1,tree[i].right+1); //递归遍历huffman树 dfs(t-1,0); //按照输入顺序,输出前N个编码,也就是你输入的字符的编码 for(int i=0;i<N;i++) printf("%c:%s\n",tree[i].ch,tree[i].code); } }