数据结构—哈夫曼编码
1.哈夫曼树简介
哈夫曼(Huffman)编码算法是基于二叉树构建编码压缩结构的,它是数据压缩中经典的一种算法。算法根据文本字符出现的频率,重新对字符进行编码。因为为了缩短编码的长度,我们自然希望频率越高的词,编码越短,这样最终才能最大化压缩存储文本数据的空间。
我们使用二叉树来构建哈夫曼树并生成哈夫曼编码. 实际上,哈夫曼树构造的过程就是最优二叉树的构建过程.例如:如果{a,b,c,d,e} 的权值为 {5,8,2,10,13},则生成的最优二叉树为:
生成哈夫曼树之后,各个需要编码的元素的编码也就得到了:
a:001, b:01, c:000, d:10, e:11
我们可以发现哈夫曼树有一些特点:
- 每个需要编码的元素在哈夫曼树中都是作为叶子节点(避免出现前缀冲突)
- 元素的权值越大,编码也就越短(频率越高,编码越短)
2.java实现哈弗曼编码
要实现哈夫曼编码,首先要构造出一颗哈夫曼树,那么应该采取怎么样的方法呢?继续使用之前的链式表示吗?仔细想一想,之前使用链式表示二叉树时,我们是从上向下构造二叉树的,但是现在如果要构造哈夫曼树,要遵循构造最优二叉树的规则,所以是从下向上构造整颗树的,所以,这里我们用双亲孩子表示法,用类型数组来表示整颗哈夫曼树
- 数据结构:
/**
* 哈夫曼树每个节点的数据结构
*/
class HfTree {
char charset;
int weight;
int parent;
int leftChild;
int rightChild;
public HfTree() {
this.parent = -1;
this.leftChild = -1;
this.rightChild = -1;
}
@Override
public String toString() {
return " " + charset +
"," + weight +
"," + parent +
"," + leftChild +
"," + rightChild;
}
}
/**
* 哈夫曼编码的数据结构
*/
class HfCode {
char charset;
int index;
Deque code;
public HfCode() {
}
public HfCode(char charset, int index) {
this.charset = charset;
this.index = index;
}
}
构造哈夫曼树的过程:
/**
* 构造哈夫曼树
* @param ht
* @param n
*/
public static void createHuffmanTree(HfTree[] ht, int n) {
for (int i = n; i < 2*n-1; i++) {
ht[i] = new HfTree();
}
for (int i = n; i < 2*n-1; i++) {
MyMin m = select(ht,i-1);
ht[i].weight = ht[m.min].weight + ht[m.nextMin].weight;
ht[i].leftChild = m.min;
ht[i].rightChild = m.nextMin;
ht[m.min].parent = i;
ht[m.nextMin].parent =