您的位置:首页 > 其它

赫夫曼编码

2016-06-28 16:53 162 查看
问题R 赫夫曼编码



思路:

对于赫夫曼来说,往左走为0,往右走为1,可以发现每一位就往下走一层。因此整体报文的长度可以用不同报文在树中的位置来确定,也就是说,符号种类*每个符号在树中的深度即为整体报文的长度;而ascll码的比特位长度为符号个数*8;

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

typedef struct
{
char data;
int parent, lchild, rchild;
int weight;
} HTree, *Huffman;
char A[500];
int len[500];

void CreateHuffmantree(Huffman &HT, int n)
{
if(n <= 1) return ;
int m = n*2-1;
for(int i=1; i<=m; i++)   //将1到m号单元的双亲和孩子的下标都初始化为
{
HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
}
for(int i=1; i<=n; i++)
{
HT[i].data = A[i-1];   //输入前n个单元中叶子节点的权值
}
for(int j=n+1; j<= m; j++ )  //通过n-1次选择,删除,合并来创建霍夫曼树
{
int m1 = 9999, m2 = 9999;     //求最小的两个
int r = -1, l = -1;     //标记两个权值最小的下标
for(int k=1; k < j; k++)
{
if(HT[k].parent == 0)
{
if(HT[k].weight < m1 && HT[k].weight != 0)
{
m2 = m1; m1 = HT[k].weight;
r = l; l = k;
}
else
{
if(HT[k].weight <= m2 && HT[k].weight != 0)
{
m2 = HT[k].weight;
r = k;
}
}
}
}
HT[l].parent = HT[r].parent = j;
HT[j].lchild = l;
HT[j].rchild = r;
HT[j].weight = HT[l].weight + HT[r].weight;
}
}

void Huffmannum(Huffman &HT, int Hc[], int x)
{
if(x == 1)   //只有一个节点的情况
{
Hc[0] = 1;
}
else
{
for(int i=1; i<=x; i++)  //从第一个节点开始搜寻
{
Hc[i] = 0;
int par = HT[i].parent;
while(par != 0)    //回溯求双亲节点
{
Hc[i]++;    //求该值在树中的层次,因为赫夫曼编码的长度就是该点在树中的高度
par = HT[par].parent;
}
}
}
}

int main()
{
while(scanf("%s",A) != EOF)
{
if( !strcmp(A, "END") ) break;
int k = 2;
int le = strlen(A);
HTree *HT = new HTree[strlen(A) + 1];    //定义一颗树
for(int t=1; t<=le; t++)
HT[t].weight = 0;
for(int i=1; i<=le; i++)
{
int j;
for(j=1; j<k; j++)  //从第一位开始搜,如果出现了和A[i]相同的就++作为该值的权值
{
if(HT[j].data == A[i-1])
{
HT[j].weight ++;
break;
}
}
if(j == k)  //没找到
{
HT[k-1].data = A[i-1];  //将A[i]加入到HT树中
HT[k-1].weight++;     //并且该值的权值加一
k++;  //K为字符种类数
}
}
k -= 2;
CreateHuffmantree(HT,k);
Huffmannum(HT,len,k);
double sum = 0;
for(int i=1; i<=k; i++)
{
sum += len[i]*HT[i].weight;   //编码的长度乘以该码的个数就是该码在整个编码中的总长度
}
int cnt = le*8;
printf("%d %.0f %.1f\n",cnt,sum,cnt/sum);
}
return 0;
}


还有一种方法是常规的,也就是建立一颗赫夫曼树后,求出每个符号的赫夫曼编码,再求出长度,下次补上
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: