一种huffmantree的写法
在这个代码里我规定了字符集是英文字母,输入是26行,每行代表一个字母的频数(从a~z);为了方便起见,在储存中我用小写英文字母表示。
(暂时只放代码,详解的话过阵子再补充)
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();
}
}