在这个代码里我规定了字符集是英文字母,输入是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();
	}
	
}