赫夫曼编码在通讯中应用广泛,赫夫曼树的建树实际上是一个贪心过程,根据所给的字符权值,优先选取权值小的建树,这样子到最后就可以缩短电文的长度。
e.g.
如果有A~H八个字符编码,如下图:
实现如下:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
int s1,s2;
int m;
char str[10]={'$','A','B','C','D','E','F','G','H'};
typedef struct {
char ch;
int data;
int p,lc,rc;
}Htree,*Hufftree;
typedef char* Huffcode;
void select (Hufftree &Ht,int n)
{
//char *cd;
int min1,min2;
min1=min2=INF;//找最小权值
s1=s2=0;//纪录最小权值的位置
int i;
for (i=1;i<=n;i++)
{
if (!Ht[i].p)
if (Ht[i].data<min1)
{
min2=min1;
s2=s1;
min1=Ht[i].data;
s1=i;
}
else if (Ht[i].data<min2)
{
s2=i;
min2=Ht[i].data;
}
}
}
void Huffman(Hufftree &Ht,Huffcode Hc[],int *w,int n)
{
int start;
char *cd;
int i,c,f;
if (n<1)
return;
m=2*n-1;//静态链表总长度
Ht=(Htree*)malloc ((m+1)*sizeof(Htree));
for (i=1;i<=n;i++)
{
Ht[i].ch=str[i];
Ht[i].data=w[i-1];
Ht[i].p=0;
Ht[i].lc=-1;
Ht[i].rc=-1;
}//录入数据
for(i=n+1;i<=m;i++)
{
Ht[i].data=0;
Ht[i].lc=-1;
Ht[i].rc=-1;
Ht[i].p=0;
}//初始化
for (i=n+1;i<=m;i++)
{
select(Ht,i-1);
Ht[s1].p=i;
Ht[s2].p=i;
Ht[i].lc=s1;
Ht[i].rc=s2;
Ht[i].data=Ht[s1].data+Ht[s2].data;//更新节点权值
}//
cd=(char *)malloc (n*sizeof(char));
start=0;
cd[n-1]='\0';
for (i=1;i<=n;i++)
{
start=n-1;
for(c=i,f=Ht[i].p;f!=0;c=f,f=Ht[f].p)
{
if (Ht[f].lc==c)
cd[--start]='0';
else
cd[--start]='1';
}
Hc[i]=(char*)malloc((n-start)*sizeof(char));
strcpy (Hc[i],&cd[start]);
}
}
void decode(Hufftree &Ht)
{
int i,j=0;
i=m;
char b[20];
printf("输入编码(End #):\n");
scanf("%s",b);
printf("Results:\n");
while(b[j]!='#')
{
//printf("%c ",b[j]);
if(b[j]=='0')
i=Ht[i].lc;
else
i=Ht[i].rc;
if(Ht[i].lc==-1)
{
printf("%c",Ht[i].ch);
i=m; //每次译码从头开始
}
j++;
}
printf("\n");
}
int main ()
{
Hufftree Ht;
Huffcode *Hc;
int w[20];
int i,n;
cout<<"Coding"<<endl;
printf("编码字符个数:\n");
scanf("%d",&n);
Hc=(Huffcode*)malloc(n*sizeof(Huffcode));
printf("编码的字符的频率:\n");
for (i=0;i<n;i++)
scanf("%d",&w[i]);
Huffman(Ht,Hc,w,n);
printf("字符编码为:\n");
cout<<"字符 权值 编码"<<endl;
for (i=1;i<=n;i++)
{
printf ("%c %d %s\n",str[i],w[i-1],Hc[i]);
}
cout<<"Decoding"<<endl;
decode(Ht);
return 0;
}