/*
功能Function Description: 赫夫曼编码---正误待验证(调试时候感觉有地方好像出错了)
开发环境Environment: DEV C++ 4.9.9.1
技术特点Technique:
版本Version:
作者Author: 可笑痴狂
日期Date: 20120803
备注Notes:
作用:
输入大写字母组成的字符串,然后以其出现的次数为权重进行编码
*/
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef struct Node
{
unsigned int weight;
unsigned int parent,left,right;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void HuffmanCoding(int *w,int n,char *s)
{
HuffmanTree HT;
HuffmanCode HC;
HuffmanTree p;
int m,i,j,s1,s2,min1,min2,c,f,start;
if(n<1)
return;
m=2*n-1;
HT=new HTNode[m+1]; //0号单元没用
for(p=HT+1,i=1;i<=n;++i,++p,++w) //初始化
{
p->weight=*w;
p->parent=0;
p->left=0;
p->right=0;
}
for(;i<=m;++i,++p)
{
p->weight=0;
p->parent=0;
p->left=0;
p->right=0;
}
for(i=n+1;i<=m;++i)
{
min1=min2=0x7fffffff;
//在HT[1,2,.....i-1]中选择parent为0且weight值最小的两个结点,其序号分别为s1、s2
for(j=1;j<i;++j)
{
if(HT[j].parent==0&&min1>HT[j].weight)
{
min1=HT[j].weight;
s1=j;
}
}
HT[s1].parent=i;
for(j=1;j<i;++j)
{
if(HT[j].parent==0&&min2>HT[j].weight)
{
min2=HT[j].weight;
s2=j;
}
}
HT[s2].parent=i;
HT[i].left=s1;
HT[i].right=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
//从叶子节点到根逆向求每个字符的赫夫曼编码
HC=new char*[n+1]; //分配n个字符编码的头指针向量
char* cd=new char[n]; //分配求编码的工作空间
cd[n-1]='\0';
for(i=1;i<=n;++i) //逐个字符求其编码
{
start=n-1; //编码结束符标志
for(c=i,f=HT[i].parent;f;c=f,f=HT[f].parent) //从叶子到根逆向求编码
if(HT[f].left==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=new char[n-start];
strcpy(HC[i],&cd[start]);
}
delete cd;
for(i=0;i<n;++i) //输出编码
cout<<s[i]<<": "<<HC[i+1]<<endl;
}
int main()
{
char s[1000];
int i,j;
int weight[27];
/*
HuffmanTree HT;
HuffmanCode HC;
*/
cout<<"请输入字符串(大写字母):"<<endl;
while(cin>>s)
{
memset(weight,0,sizeof(weight));
int len=strlen(s);
for(i=0;i<len;++i)
++weight[s[i]-'A'];
for(i=0,j=0;i<26;++i) //去掉没有出现过的字母,将字母和权值都压缩存储到原来的空间中
if(weight[i])
{
s[j]=i+'A';
weight[j++]=weight[i];
}
cout<<"赫夫曼编码为:"<<endl;
HuffmanCoding(weight,j,s);
cout<<"请输入字符串(大写字母):"<<endl;
}
return 0;
}
功不成,身已退
浙公网安备 33010602011771号