赫夫曼树
定义: 给定N个权值作为N个叶子节点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为赫夫曼树(Huffman Tree)。
叶子的带权路径
叶子节点的带权路径=叶子节点的权+从根节点在叶节点的路径长
例如:
叶子节点4的带权路径= 4 *2
叶子节点7的带权路径= 7 *2
树的带权路径长度WPL
WPL(a) = (9+4+5+2)X2=40
WPL(b) = 9 +5X2+4X3+2X3=37
WPL© = 4 + 2X2+5X3+9X3=50
注:权值越大的节点离根节点越近的二叉树才是最优二叉树
创建赫夫曼树的流程分析
注:
1.黑色是给定的节点
2.绿色的我们自己构成的节点
选择的两个节点,小的为左节点,大的为右节点
赫夫曼树的代码实现
public static TreeNode createHuffmanTree(int[] arr) {
//使用数组中的元素创建若干个二叉树,节点仅仅为1
List<TreeNode> list = new ArrayList<>();
for (int a : arr
) {
list.add(new TreeNode(a));
}
while (list.size() > 1) {
//利用比较器排序
Collections.sort(list);
//选取最小的值和次小的值充当左子节点和右子节点
TreeNode leftNode = list.get(0);
TreeNode rightNode = list.get(1);
TreeNode parentNode = new TreeNode(leftNode.value + rightNode.value);
parentNode.leftNode = leftNode;
parentNode.rightNode = rightNode;
//从列表中删除左子节点和右子节点
list.remove(0);
list.remove(0);
//将新的权值放回列表
list.add(parentNode);
}
return list.get(0);
}
赫夫曼编码概述
步骤:
1.将字符出现的频率当做权值
2.构造赫夫曼树
3.左指针为0,右指针为1,路径当做字符的编码
注:字符的编码所构成的表别成为赫夫曼编码表
优点:
1.在使用不定长编码时,任何单词的编码不会是其他单词编码的前缀
2.不定长编码相比定长编码 文件压缩率更低,因为需要传送的编码更短
赫夫曼编码实现
步骤:
1.统计字符并排序
2.创建赫夫曼树
3.创建赫夫曼编码表
4.编码
package Tree.HuffmanCode;
public class TreeNode implements Comparable</