#include<iostream>
#include<string>
using namespace std;
struct hufftree
{
int parent;
int lchild;
int rchild;
int weight;
string flag;
};
struct lowestnode
{
char ch; //统计各个字符
int ch_num; //字符的频率
};
void coding(int length,hufftree tree[],int n,int &a,int &b)
{ //函数功能:一组数中选择出最小的两个数
int i;
int r,s;
r=s=length;
for(i=0;i<n;i++)
{
if((tree[i].weight<r)&&(tree[i].parent==-1))
{ //"<"而不是"<="代表若最小的数有多个选择前
r=tree[i].weight; //面的旧的两个这样避免增加树的层数
a=i;
}
}
for(i=0;i<n;i++)
{
if((tree[i].weight<s)&&(i!=a)&&(tree[i].parent==-1))
{
s=tree[i].weight;
b=i;
}
}
}
void sort(lowestnode node[],int n) //给结构体排序
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<(n-1);j++)
{
if(node[j].ch_num==node[j+1].ch_num)
{ //如果频率相同,按字母表排序
if(node[j].ch>node[j+1].ch)
{ //按频率由大到小
int temp1;
char ch_temp1;
temp1=node[j].ch_num;
ch_temp1=node[j].ch;
node[j].ch_num=node[j+1].ch_num;
node[j].ch=node[j+1].ch;
node[j+1].ch_num=temp1;
node[j+1].ch=ch_temp1;
}
}
if(node[j].ch_num<node[j+1].ch_num)
{
int temp;
char ch_temp;
temp=node[j].ch_num;
ch_temp=node[j].ch;
node[j].ch_num=node[j+1].ch_num;
node[j].ch=node[j+1].ch;
node[j+1].ch_num=temp;
node[j+1].ch=ch_temp;
}
}
}
}
void free(string str) //编码函数
{
int length=str.length();
lowestnode *node=new lowestnode[length];
int i,j;
for(i=0;i<length;i++)
{
node[i].ch_num=0;
}
int type=0;
for(i=0;i<length;i++)
{
for(j=0;j<type;j++)
{
if(str[i]==node[j].ch/*||(node[j].ch>='a'&&node[j].ch<='z'&&str[i]+32==node[j].ch)*/)
{
node[j].ch_num++;
break;
}
}
if(j==type)
{
/*if(str[i]>='A'&&str[i]<='Z')
node[j].ch=str[i]+32;
else
*/node[j].ch=str[i];
node[j].ch_num++;
type++;
}
}
sort(node,type);
for(i=0;i<type;i++)
cout<<"字符"<<node[i].ch<<"出现了 "<<node[i].ch_num<<" 次"<<endl;
hufftree *huff=new hufftree[2*type-1];
hufftree temp;
string *code=new string[2*type-1];
for(i=0;i<2*type-1;i++)
{
huff[i].lchild=-1;
huff[i].rchild=-1;
huff[i].parent=-1;
huff[i].flag=-1;
}
for(j=0;j<type;j++)
{
huff[j].weight=node[j].ch_num;
}
int min1,min2;
for(int k=type;k<2*type-1;k++)
{
coding(length,huff,k,min1,min2); //codeing函数选出的数当成
huff[min1].parent=k; //孩子结点
huff[min2].parent=k;
huff[min1].flag="0";
huff[min2].flag="1";
huff[k].lchild=min1;
huff[k].rchild=min2;
huff[k].weight=huff[min1].weight+huff[min2].weight;
}
for(i=0;i<type;i++)
{
temp=huff[i];
while(1)
{
code[i]=temp.flag+code[i];
temp=huff[temp.parent];
if(temp.parent==-1)
break;
}
}
//cout<<"字符串的每个字符huffman编码为:"<<endl;
//for(i=0;i<type;i++)
// cout<<node[i].ch<<" "<<code[i]<<endl;
cout<<"总共有 "<<type<<" 个字符"<<endl;
cout<<"整个字符串的huffman编码为:"<<endl;
for(i=0;i<length;i++)
{
for(j=0;j<type;j++)
{
if(str[i]==node[j].ch)
cout<<code[j];
}
}
delete[] node;
node=NULL;
delete[] huff;
huff=NULL;
delete[] code;
code=NULL;
}
int main()
{
char an;
do
{
int ans;
cout<<"想编码还是解码?";
cout<<"解码输入 0 编码输入 1 : ";
cin>>ans;
if(ans==1)
{
string str;
cin.clear();
cin.sync();
cout<<"请输入一个字符串后回车两下:"<<endl;//vc6.0的bug
getline(cin,str,'\n');
free(str);
cout<<endl;
}
else if(ans==0) //解码主体
{
cout<<"请输入字符种类个数(数字):";
int n,i=0,j=0,m;
int length=0;
cin>>n;
char c[5];
cout<<"按顺序输入字符(包括空格)和频率:"<<endl;
lowestnode *yuan=new lowestnode[n];
for(m=0;m<n;m++)
{
cout<<"字符:";
cin.clear();
cin.sync();
cin.getline(c,2);
yuan[m].ch=c[0];
cout<<yuan[m].ch<<"的";
cout<<"频率:";
cin>>yuan[m].ch_num;
}
for(i=0;i<n;i++)
{
length=length+yuan[i].ch_num;
}
sort(yuan,n);
hufftree *huff=new hufftree[2*n-1];
hufftree temp;
string *code=new string[2*n-1];
for(i=0;i<2*n-1;i++)
{
huff[i].lchild=-1;
huff[i].rchild=-1;
huff[i].parent=-1;
huff[i].flag=-1;
}
for(j=0;j<n;j++)
{
huff[j].weight=yuan[j].ch_num;
}
int min1=0,min2=0;
for(int k=n;k<2*n-1;k++)
{
coding(length,huff,k,min1,min2);
huff[min1].parent=k;
huff[min2].parent=k;
huff[min1].flag="0";
huff[min2].flag="1";
huff[k].lchild=min1;
huff[k].rchild=min2;
huff[k].weight=huff[min1].weight+huff[min2].weight;
}
for(i=0;i<n;i++)
{
temp=huff[i];
while(1)
{
code[i]=temp.flag+code[i];
temp=huff[temp.parent];
if(temp.parent==-1)
break;
}
}
//cout<<"字符串的每个字符huffman编码为:"<<endl;
//for(i=0;i<n;i++)
//cout<<yuan[i].ch<<" "<<code[i]<<endl;
cout<<"........................"<<endl;
string s;
cout<<"请输入编码:"<<endl;
cin>>s;
while(s.length()>(n-1)*length)
{
cout<<"输入编码溢出";
cout<<"请再输入一次编码:"<<endl;
cin.clear();
cin.sync();
cin>>s;
}
string *fang=new string[length];
for(i=0,m=0;m<length;)
{
for(j=0;j<code[i].size();j++)
{
if(s[j]!=code[i][j])
{
i++;
if(i==n)
{
cout<<"输入编码错误";
return 0;
}
break;
}
else if(j==(code[i].size()-1))
{
fang[m]=yuan[i].ch;
s=s.erase(0,j+1);
i=0,m++;
break;
}
}
}
for(i=0;i<length;i++)
{
cout<<fang[i];
}
cout<<endl;
delete[] yuan;
yuan=NULL;
delete[] huff;
huff=NULL;
delete[] code;
code=NULL;
delete[] fang;
fang=NULL;
}
cout<<"输入 y or Y 继续:";
cin>>an;
}while(an=='y'||an=='Y');
return 0;
}
可包括空格的字符串编码,解码需要输入字符个数和权重。不过程序过于繁琐,还能优化。