数据结构06-哈夫曼树
一、哈夫曼树的基本概念
1.哈夫曼树
给定n个权值作为n个叶子节点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的节点离根较近。
哈夫曼树一般是用来数据压缩的,比如哈夫曼编码。
2.路径和路径长度
在一棵树中,从一个节点往下可以达到的孩子或孙子节点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L-1。
3.节点的权及带权路径长度
若将树中节点赋给一个有着某种含义的数值,则这个数值称为该节点的权。节点的带权路径长度为:从根节点到该节点之间的路径长度与该节点的权的乘积。
4.树的带权路径长度
树的带权路径长度规定为所有叶子节点的带权路径长度之和,记为WPL。
二、哈夫曼树的实现
设有n个权值,则构造出的哈夫曼树有n个叶子节点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
- 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个节点);
- 在森林中选出两个根节点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根节点权值为其左、右子树根节点权值之和;
- 从森林中删除选取的两棵树,并将新树加入森林;
- 重复2、3步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
/**
* 添加元素:添加时从小到大的权重顺序添加
*
* @param node 需要添加的节点
*/
public void put(Node<E> node) {
if (root == null) {
root = node;
return;
}
Node<E> old = root;
root = new Node<E>();
root.bran = old.bran + node.bran;
if (old.bran < node.bran) {
root.left = old;
root.right = node;
} else {
root.left = node;
root.right = old;
}
old.parent = root;
node.parent = root;
}
三、哈夫曼编码
将字符用0和1组成的不同长度的编码表示,每个字符的编码从头比较时,都不会相互包含,这样就可以正确识别每一个字符。现在将出现次数最多的字符用最小长度的编码表示,将出现次数最少的字符用最大长度的编码表示,这样得到的数据比用传统编码表示的数据要小,从而实现数据压缩。这样的编码就是哈夫曼编码。
/**
* 将哈夫曼树转为哈夫曼编码
* 哈夫曼树每个节点都有叶子节点,最下面的分支节点有两个叶子节点,我们现在要遍历所有的叶子节点,并用0和1表示,即为哈夫曼编码。
*/
public List<HuffmanCode<E>> getHuffmanCode() {
Node<E> curr = root;
if (curr == null) {
return null;
}
List<HuffmanCode<E>> list = new ArrayList<>();
String code = "";
while (curr != null) {
Node<E> left = curr.left;
Node<E> right = curr.right;
//到达叶子节点就退出
if (left == null && right == null) {
//只有一个节点时
if (curr == root) {
list.add(new HuffmanCode<E>(curr.data, code + "0"));
}
break;
}
//如果左子节点为叶子节点,则将其取出,并用0表示,然后遍历右子节点
if (left.left == null && right.left != null) {
list.add(new HuffmanCode<E>(left.data, code + "0"));
curr = right;
code += "1";
//如果右子节点为叶子节点,则将其取出,并用1表示,然后遍历左子节点
} else if (right.left == null && left.left != null) {
list.add(new HuffmanCode<E>(right.data, code + "1"));
curr = left;
code += "0";
//如果左右子节点都是叶子节点,则都取出,并且遍历结束
} else if (right.left == null && left.left == null) {
list.add(new HuffmanCode<E>(right.data, code + "1"));
list.add(new HuffmanCode<E>(left.data, code + "0"));
curr = null;
}
}
return list;
}
最后
数据结构与算法专题:https://www.jianshu.com/nb/25128590
喜欢请点赞,谢谢!