以字母出现的频率建一颗二叉树,频率越大的字母的赫夫曼编码越短,这样保证任意一个字母的编码不会是另一个字母编码的前缀,然后遍历吧.(赫夫曼编码不是唯一的)
//Word .java,存字母信息
public class Word {
char c;
int w;//出现次数
}
//HuffmanNode.java,每个赫夫曼节点信息
public class HuffmanNode {
char c;
int weight;
int tag;//tag是一个标记,用于建树时的Select函数,也就是看这个点是否已经在树中
int father;
int lchild;
int rchild;
StringBuilder s;
HuffmanNode(){
weight=0;
tag=father=lchild=rchild=-1;
s=new StringBuilder("");
}
}
//HuffmanTree.java
public class HuffmanTree {
HuffmanNode[] tree;
int num;
HuffmanTree(int n,Word[] w){//n个字母的赫夫曼树有n*2-1个节点,生成这n*2-1个节点
num=n*2-1;
tree = new HuffmanNode[num];
for(int i=0;i<num;i++)
tree[i]=new HuffmanNode();
for(int i=0;i<n;i++){
tree[i].c=w[i].c;
tree[i].weight=w[i].w;
}
}
int Select(){//选出当前没被选过的节点中权值最小的
int ans=1000000000,pos=-1;
for(int i=0;i<num;i++){
if(tree[i].tag==-1&&tree[i].weight!=0){
if(tree[i].weight<ans){
ans=tree[i].weight;
pos=i;
}
}
}
tree[pos].tag=1;//标记为已选
return pos;
}
void BuildTree(int n){//建树
for(int i=n;i<num;i++){
int i1=Select();
int i2=Select();
tree[i1].father=tree[i2].father=i;
tree[i].lchild=i1;
tree[i].rchild=i2;
tree[i].weight=tree[i1].weight+tree[i2].weight;
}
}
void HuffmanCode(int n){//编码
for(int i=0;i<n;i++){
int j=i;
StringBuilder ans=new StringBuilder("");
while(tree[j].father!=-1){
int fa=tree[j].father;
if(tree[fa].lchild==j) ans.append("0");
else ans.append('1');
j=fa;
}
tree[i].s=ans;
System.out.print(tree[i].c+"的赫夫曼编码是: ");
System.out.println(ans.reverse());
}
}
}
//测试程序
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String s = in.next();
int[] vis = new int[26];
Arrays.fill(vis, 0);
int num=0,t=0;
//统计每个字符的频率,此测试程序的输入只能是小写字母。
for(int i=0;i<s.length();i++){
int a=s.charAt(i)-'a';
if(vis[a]==0) num++;
vis[a]++;
}
//一共出现了num个字母
Word[] word = new Word[num];
for(int i=0;i<num;i++){
word[i] = new Word();
}
//把num个字母存入Word.
for(int i=0;i<26;i++){
if(vis[i]!=0){
word[t].c=(char)('a'+i);
word[t].w=vis[i];
t++;
}
}
HuffmanTree tree = new HuffmanTree(num,word);
tree.BuildTree(num);
tree.HuffmanCode(num);
}
}