哈夫曼树的应用
要传输一则报文内容如下:
“AAAAAAAAAAAAAAABBBBBBBBBCCCCCCCCDDDDDDDDDDDDEEEEEEEEEEFFFFF”
请为这段报文设计哈夫曼编码,要求如下:
- 请计算出每个字符出现的概率,并以概率为权重来构造哈夫曼树,写出构造过程、画出最终的哈夫曼树,得到每个字符的哈夫曼编码。
- 请将上述设计哈夫曼编码的过程,用代码来实现,并输出各个字母的哈夫曼编码。(有代码,有运行结果的截图)
(1) 由上述这段编码可得,ABCDEF的概率分别为:15/59、9/59、8/59、12/59、10/59、5/59。
构造哈夫曼树的目的是找出存放一串字符所需的最少的二进制编码,其构造过程就是:找出结点权值中最小的两个,把这两个作为左右子树构造成一棵新的二叉树,二叉树根结点的值就是其左右子树根结点权值之和,在森林中删除此次找到的两个数,并加入此次最小两个数的和,不断重复这一过程,直到树中只含有一棵树为止。
构造过程如图所示
最终的结果如图所示:
每个字符的编码依次为:
A:10 B:110 C:011 D:00 E:111 F:010
(2)代码为:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define ERROR 0
typedef struct HTNode
{
int weighted;//权重
int Parents;//双亲
int Lchild, Rchild;//左右孩子
};
typedef HTNode * huffman;
typedef char** haffmancode;
void chushihua(huffman& T, int num)//初始化工作 num是结点个数
{
int length = num * 2 - 1;
int i;
int j;
int legth=length+1;
T = (huffman)malloc((legth + 1) * sizeof(HTNode));
for (i = 1; i <= length; i++)
{
T[i].Parents = ERROR;//初始化 ERROR=0
T[i].Rchild = ERROR;//初始化 ERROR=0
T[i].Lchild = ERROR;//初始化 ERROR=0
}
printf("请输入每个叶子的权值\n");
for (j = 1; j <=num; j++)
{
scanf("%d", &T[j].weighted);//初始化
}
}
void creat(huffman &T,int num)//构造haffman树
{
int i;
int j;
int p, q;
int m1, m2;
if (num < 2)
{
printf("ERROR\n");
return;
}
chushihua(T, num);
int s1, s2;
for (i = num+1; i <2 * num ; i++)
{
m1 = 10000000;//定义最大量
m2 = m1;
p = q = 0;
for (j = 0; j < i; j++)
{
if (T[j].weighted < m1 && T[j].Parents == ERROR)
{
m2 = m1; q = p;
m1 = T[j].weighted;
p = j;
}
else if(T[j].weighted < m2 && T[j].Parents == ERROR)
{
m2 = T[j].weighted;
q = j;
}
}
T[p].Parents = i;
T[q].Parents = i;
T[i].Lchild = p;
T[i].Rchild = q;
T[i].weighted = T[p].weighted + T[q].weighted;
}
}
typedef struct
{
char ch;
char bits[10];
}CodeNode;
typedef CodeNode* HuffmanCode;
void lasthuffman(huffman T,haffmancode &t,int num)//编码
{
t= (char**)malloc((num+1) * sizeof(char*));
char* ch = (char*)malloc(num * sizeof(char));
ch[num - 1] = '\0';
int i;
int m;
int point;
int result;
for (i = 1; i <=num; i++)
{
m = num - 1;
point = i;
result = T[i].Parents;
while (result!=0)
{
m--;
if (T[result].Lchild == point)
{
ch[m] = '0';
}
else
{
ch[m] = '1';
}
point = result;
result = T[result].Parents;
}
t[i] = new char[num - m];
strcpy(t[i], &ch[m]);
}
delete ch;
}
int main()
{
int num;
printf("请输入结点的个数:");
scanf("%d", &num);
huffman T;
creat(T, num);
haffmancode t;
printf("请输入各点字符\n");
char ch[1000];
getchar();
for (int k = 0; k < num; k++)
{
scanf("%c", &ch[k]);
}
lasthuffman(T, t, num);
for (int i = 1; i <=num; i++)
{
printf("%c的前缀编码为:%s\n",ch[i-1],t[i]);
}
}
运行结果为: