哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码(有时也称为霍夫曼编码)。
霍夫曼编码即是一种最优二叉树的实现。我们为什么要采用编码呢?计算机中的信息都是以二进制存储的,如字符编码的ASCII码,BCD码等等。然而大量的二进制的存储会造成空间的浪费,我们知道有些数据含有的0或1比较多,多余的信息我们就可以把它去除,所以出现了很多的压缩算法。常见的有LZW、DEFLAT、LZ等等(多谢 ruki 指出错误之处,LZ系列的压缩率的确比霍夫曼编码高)。然而为什么不用霍夫曼编码呢?从理论上说霍夫曼编码的效率是最高的,但是其执行效率却比较差,也就是说数据压缩所需要的时间比较长,我们总不会希望压缩1G的文件却使用半小时吧。所以前面提到的那些算法在速度上比霍夫曼编码快而已,数据压缩率却没有霍夫曼编码的高。那为什么我们还要了解霍夫曼编码呢?
其实霍夫曼编码虽然在数据压缩领域使用的较少,但是在通信领域却得到广泛的应用。霍夫曼编码的基本原理即是从底向上生成二叉树,如果出现多个二叉树则将其合并。例如:
有一组数据,3 4 7 8 9 12 16
天蓝色的数字是原始数据,红色数字是其下方两个数字之和。
第一步:
7
3 4
第二步:
14
7 7
3 4
第三步:
14
7 7 17
3 4 8 9
第四步:
14
7 7 17 28
3 4 8 9 12 16
第五步: 将子树合并
59
31 28
14 17 12 16
7 7 8 9
3 4
代码如下
#include <stdio.h>
#define MAX_WEIGHT 10000
#define MAX_LEAF 30
#define MAX_NODE MAX_LEAF*2-1
#define MAX_BIT 12
typedef int data_t;
typedef struct huff_node {
int weight;
int parent;
int lchild;
int rchild;
} huff_t;
typedef struct huff_code {
int bit[MAX_BIT];
int start;
} huff_code_t;
void huffman_tree(huff_t huff_tree[], int num, data_t weight[])
{
int i, j, m1, m2, x1, x2, n = num;
for (i = 0; i < 2 * n - 1; i++) {
huff_tree[i].weight = 0;
huff_tree[i].parent = -1;
huff_tree[i].lchild = -1;
huff_tree[i].rchild = -1;
}
for (i = 0; i < n; i++) {
huff_tree[i].weight = weight[i];
}
for (i = 0; i < n - 1; i++) {
m1 = m2 = MAX_WEIGHT;
x1 = x2 = 0;
for (j = 0; j < n + i; j++) {
if (huff_tree[j].weight < m1
&& huff_tree[j].parent == -1) {
m2 = m1;
x2 = x1;
m1 = huff_tree[j].weight;
x1 = j;
} else if (huff_tree[j].weight < m2
&& huff_tree[j].parent == -1) {
m2 = huff_tree[j].weight;
x2 = j;
}
}
huff_tree[x1].parent = n + i;
huff_tree[x2].parent = n + i;
huff_tree[n + i].weight = huff_tree[x1].weight
+ huff_tree[x2].weight;
huff_tree[n + i].lchild = x1;
huff_tree[n + i].rchild = x2;
}
}
void huffman_code(huff_t arry[], int num)
{
int i, j, c, p;
huff_code_t cd, huff_code[MAX_NODE];
for (i = 0; i < num; i++) {
cd.start = num - 1;
c = i;
p = arry[c].parent;
while (p != -1) {
if (arry[p].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
c = p;
p = arry[c].parent;
}
for (j = cd.start + 1; j < num; j++)
huff_code[i].bit[j] = cd.bit[j];
huff_code[i].start = cd.start;
}
for (i = 0; i < num; i++) {
for (j = huff_code[i].start + 1; j < num; j++)
printf("%d\t", huff_code[i].bit[j]);
printf("\n");
}
}
int main()
{
const int length = 7;
data_t weight[7] = { 3,4,7,8,9,12,16 };
huff_t arry[MAX_NODE];
huffman_tree(arry, length, weight);
huffman_code(arry, length);
printf("\n");
return 0;
}
今天就到这,下次接着写。:)