/* 功能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; }