赫夫曼树和赫夫曼编码(C语言版)
一.赫夫曼树
(一)赫夫曼树的定义及表示方法
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度(WPL)最短的树,权值较大的结点离根较近。
二.赫夫曼编码
(一)赫夫曼编码的定义及表示方法
将赫夫曼树权值的左分支全部改为0,右分支全部改为1(左0右1)
从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该节点对应字符的编码也叫赫夫曼编码
举个栗子(利用上图的赫夫曼树):
三.C语言编写
(一)代码设计思路
1构造赫夫曼树
2在哈夫曼树上构建赫夫曼编码
3输出赫夫曼编码
4计算出WSL的值
(二)部分源代码函数分析
1.主函数
//动态分配数组存储赫夫曼树, 设计一组输入数据(假定为一组整数),能够对其进行如下操作:
//编写主程序,实现对各不同的算法调用。
int main(){
int n = 8;
HTNode ht[M];
HuffmanCode hcd;
//创建一个新的顺序表,实现动态空间分配的初始化;
hcd = (HuffmanCode)malloc((2 * n)*sizeof(char*));
//对输入的数据构造成一棵Huffman 树;
CreateHT(ht, n);
//根据生成的Huffman 树进行Huffman 编码;
CreateHCode(ht, hcd, n);
//实现对输入数据的Huffman 编码输出;
DispHCode(ht, hcd, n);
printf("\n");
system("pause");
return 0;
}
2.构建哈夫曼树
ps:在构建代码思路是我是将所有空结点都设为0,在此代码中均设为了-1
//构造具有n个结点的哈夫曼树
void CreateHT(HTNode ht[], int n){
char *str[] = {
"A", "B", "C", "D", "E", "F", "G", "H" };//待编码字符,这是一个字符串数组
int fnum[] = {
5, 29, 7, 8, 14, 23, 3, 11 };//待编码字符出现的频率
int i, k;
int lnode, rnode;
int min1, min2;
//TODO:此处为方便调试将数值固定,后续可用scanf语句进行修改
for (i = 0; i<n; i++){
//用待编码字符以及频率初始化ht[]数组
strcpy(ht[i].data, str[i]);//strcpy将str[]复制到ht[]中
ht[i].weight = fnum[i];//把fnum中的值放入ht[].weight
}
for (i = 0; i<2 * n - 1; i++){
//n个叶子结点,总共2n-1个结点
//ht[]数组中所有结点的相关域初值设置为-1
ht[i].parent = -1;
ht[i].lchild = -1;
ht[i].rchild = -1;
}
for (i = n; i<2 * n - 1; i++){
min1 = 32767