一种huhffman树的写法
在这个代码里我规定了字符集是英文字母,输入是26行,每行代表一个字母的频数(从a~z);为了方便起见,在储存中我用小写英文字母表示。
(暂时只放代码,详解的话过阵子再补充由于对于一组字符集和频数对应的huffman编码会有好多种,所以这里给出一个我自己习惯的写法
20:11开放完整代码,但是温馨提示,直接提交会wa。请仔细看注释。
/* 由于对于一组字符集和频数对应的huffman编码会有好多种,所以这里给出一个我自己习惯的写法 */ #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; struct node{ //用来存每个字符的频数和编码,以及字符本身 char n;int val; int a[100];int l; node() {n=0;memset(a,0,sizeof(a));l=0;val=0;} void print() {printf("%c ",n);for(int i=l;i>=1;i--) printf("%d",a[i]);puts("");} void add1(){a[++l]=1;return ;}//编码前补1 void add0(){a[++l]=0;return ;}//编码前补0 }nd[100]; struct tree{ //用来构建小根堆 node ins[100];int len; int siz; tree() {memset(ins,0,sizeof(ins));len=0;siz=0x3f3f3f3f;} friend bool operator <(const tree &a,const tree &b) {return a.siz<b.siz;}//规定大小比较 friend bool operator >(const tree &a,const tree &b) {return a.siz>=b.siz;} }t[100]; int qwq; //手写小根堆 tree q[100];int l; void push(tree a) { q[++l]=a;int now=l; while(now>1) { int fa=now>>1; if(q[now]<q[fa]) { swap(q[fa],q[now]); now = fa; } else break; } return ; } bool empty() {return l==0;} void pop() { swap(q[1],q[l]);l--; int now = 1; int ch1=now<<1;int ch2=now<<1|1; while(now<l){//每次都和左右儿子中较小的那个比较 if(q[ch1]<q[ch2]) { if(ch1>l) break; if(q[ch1]<q[now]) { swap(q[ch1],q[now]); now=ch1; ch1=now<<1;ch2=now<<1|1; continue ; } else break; } else { if(ch2>l) break; if(q[ch2]<q[now]) { swap(q[ch2],q[now]); now=ch2; ch1=now<<1;ch2=now<<1|1; continue ; } else break; } } } tree top() {return q[1];} tree modify(const tree &a,const tree &b) {//合并两个子树 tree c; //定义先取出来的那一组在左子树,后取出来的那一组在右子树 c.siz=a.siz+b.siz; c.len=a.len+b.len; for(int i=1;i<=a.len;i++) { node book=a.ins[i]; book.add0(); //左子树补0 c.ins[i]=book; } for(int i=1;i<=b.len;i++) { node book=b.ins[i]; book.add1(); //右子树补1 c.ins[a.len+i]=book; } return c; } tree qa,qb,qc; int ans; int main() { // freopen("2.txt","r",stdin); // freopen("final.txt","w",stdout); for(int i=0;i<26;i++) { scanf("%d",&qwq); //按照顺序读取a~z的频数 nd[i].n=char(i+'a'); //每个字符的初始情况 nd[i].val=qwq; //每个字符的频数 t[i].ins[++t[i].len]=nd[i]; //对每个字符建立节点 t[i].siz=qwq; push(t[i]); //存到小根堆里 } for(int i=1;i<=25;i++) { qa=top();pop(); //每次取出两个最小的 qb=top();pop(); ans=ans+qa.siz+qb.siz; //统计wpl qc=modify(qa,qb); //合并 push(qc); //将新的子树压进堆 } printf("\nWPL=%d\n\n",ans); //输出 for(int i=1;i<=qc.len;i++) { node book=qc.ins[i]; book.print(); } }