1.哈夫曼树
假设有n个权值{w1, w2, …, wn},试构造一棵含有n个叶子结点的二叉树,每个叶子节点带权威wi,则其中带权路径长度WPL最小的二叉树叫做最优二叉树或者哈夫曼树。
特点:哈夫曼树中没有度为1的结点,故由n0 = n2+1以及m= n0+n1+n2,n1=0可推出m=2*n0-1,即一棵有n个叶子节点的哈夫曼树共有2n-1个节点
2.哈夫曼编码
通信传送的目标是使总码长尽可能的短。
变长编码的原则:
1.使用频率高的字符用尽可能短的编码(这样可以减少数据传输量);
2.任一字符的编码都不能作为另一个字符编码的开始部分(这样就使得在两个字符的编码之间不需要添加分隔符号)。这种编码称为前缀编码。
根据每种字符在电文中出现的次数构造哈夫曼树,将哈夫曼树中每个分支结点的左分支标上0,右分支标上1,把从根结点到每个叶子结点的路径上的标号连接起来,作为叶结点所代表的字符的编码。这样得到的编码称为哈夫曼编码。
思考:为什么哈夫曼编码符合变长编码的原则?哈夫曼树所构造出的编码的长度是不是最短的?
哈夫曼树求得编码为最优前缀码的原因: 在构造哈夫曼树的过程中:
1.权值大的在上层,权值小的在下层。满足出现频率高的码长短。
2.树中没有一片叶子是另一叶子的祖先,每片叶子对应的编码就不可能是其它叶子编码的前缀。即上述编码是二进制的前缀码。
假设每种字符在电文中出现的次数为wi (出现频率即为权值),其码长为li,电文中只有n种字符,则编码后电文总码长为,而哈夫曼树是WPL(树的带权路径长度)最小的二叉树,因此哈夫曼编码的码长最小。
注意:哈夫曼编码是不唯一的,这与构造哈夫曼树过程相关,但是哈夫曼树WPL是固定的。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 8 //Huffman树叶结点数
#define M 2*N-1 //Huffman树结点个数
#define MAX 1000
/*构造Huffman树和Huffman编码 */
//Huffman树和Huffman编码的存储表示
typedef struct
{
unsigned int weight;
unsigned int parent, lchild, rchild;
}HTNode,HuffmanTree[M+1]; //HuffmanTree[M+1]存储Huffman树结点
typedef char* HuffmanCode[N+1]; // HuffmanCode[N+1]存储Huffman编码字符串指针
//找出数组中无父节点且权值最小的两个节点下标存储于s1,s2且权值s1<&