最近写了个哈弗曼编码的小程序。
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define maxNum 300
struct Node{//树节点
char val;//数值
int cs;//出现次数
int left;//左孩子
int right;//右孩子
}nodes[maxNum];
//查询表
char table[maxNum];
string code[maxNum];
int showNum[maxNum];
int len=0;//节点个数
//比较函数
bool comp(const Node &node1,const Node &node2){
return node1.cs<node2.cs;
}
//走二叉树,初始化查询表
void walk(int pos,string codeStr){
if(nodes[pos].left==0&&nodes[pos].right==0){
for(int i=1;i<=len;++i){
if(table[i]==nodes[pos].val){
if(codeStr=="")
codeStr+="0";
code[i]=codeStr;
return;
}
}
}else{
string s1=codeStr+"0";
walk(nodes[pos].left,s1);
string s2=codeStr+"1";
walk(nodes[pos].right,s2);
}
}
//创建Hffman树
void init(string str){
//解析字符串
for(int i=0;i<str.length();++i){
bool isFind=false;
for(int j=1;j<=len;++j){
if(nodes[j].val==str[i]){
isFind=true;
nodes[j].cs++;
showNum[j]++;
break;
}
}
if(!isFind){
len++;
nodes[len].val=str[i];
nodes[len].cs=1;
nodes[len].left=0;
nodes[len].right=0;
//初始化查询表
table[len]=str[i];
showNum[len]=1;
}
}
//将节点按次数排序,并进行合并
int start=1;
int myend=len;
while(start!=myend){
vector<Node> vNode;
for(int i=start;i<=myend;++i){
vNode.push_back(nodes[i]);
}
sort(vNode.begin(),vNode.end(),comp);
for(int i1=start;i1<=myend;++i1){
nodes[i1]=vNode[i1-start];
}
int p1=start;
int p2=start+1;
nodes[myend+1].val=' ';
nodes[myend+1].cs=nodes[p1].cs+nodes[p2].cs;
nodes[myend+1].left=p1;
nodes[myend+1].right=p2;
myend++;
start+=2;
}
//走二叉树,初始化查询表
walk(start,"");
}
int main(){
//输入提示
cout<<"无损压缩编码试验----Huffman编码"<<endl<<endl;
cout<<"请您输入用于编码的字符串,中间请勿出现空格,换行结束输入"<<endl;
string str;
cin>>str;
//创建Hffman树
init(str);
//输出信息
cout<<endl;
cout<<"编码结果如下:"<<endl;
cout<<"***************Huffman编码表***************"<<endl;
cout<<"字符\t出现次数\t对应的编码"<<endl;
int codeLen=0;
for(int i=1;i<=len;++i){
cout<<table[i]<<"\t"<<showNum[i]<<"\t\t"<<code[i]<<endl;
}
cout<<"*******************************************"<<endl<<endl;
cout<<"将原来输入的字符串转换成对应编码如下:"<<endl;
for(int i0=0;i0<str.length();++i0){
for(int j=1;j<=len;++j){
if(table[j]==str[i0]){
cout<<code[j];
codeLen+=code[j].length();
break;
}
}
}
cout<<endl<<endl;
cout<<"性能分析如下:"<<endl<<endl;
cout<<"平均码长:"<<(codeLen*1.0)/str.length()<<endl;
double gl[300];
for(int i3=1;i3<=len;++i3)
gl[i3]=(1.0*showNum[i3])/str.length();
double H=0;
for(int i4=1;i4<=len;++i4)
H+=(log(gl[i4])/log(2))*gl[i4];
cout<<"熵的值为:"<<-H<<endl;
int wei=(int)(sqrt(len-1)+1);
cout<<"压缩比为:"<<(wei*str.length()*1.0)/(codeLen*1.0)<<endl;
return 0;
}