哈夫曼树
假设有N个结点,现在我们需要把这N个结点弄成一棵树,当然了并不是随随便便的一棵树,构造这棵树的要求是:第一:这N个结点必须是这棵树的叶子结点(即没有孩子结点的结点),第二:在这N个结点中 值大的的结点在上面,值小的的结点在下面。第三:因为要连接叶子结点,所以肯定需要创建新的结点,该新的结点就作为叶子结点的父结点,该父结点的值就是两个子结点和的值。
例子:
哈夫曼树
/*
1、先将珠宝们从小到大排序
2、找出最小的两个
3、将这两个融合起来,提炼成一颗价值叠加的玛瑙珠宝
4、重复执行以上步骤,将会提炼一颗终极珠宝-----宝格丽珠宝
*/
public class HuffmanTree {
public static void main(String[] args) {
huffmanTree();
}
public static void huffmanTree(){
jewelry jewelry1 = new jewelry(13);
jewelry jewelry2 = new jewelry(7);
jewelry jewelry3 = new jewelry(8);
jewelry jewelry4 = new jewelry(3);
jewelry jewelry5 = new jewelry(29);
jewelry jewelry6 = new jewelry(6);
jewelry jewelry7 = new jewelry(1);
List<jewelry> list = new ArrayList<jewelry>();
list.add(jewelry1);
list.add(jewelry2);
list.add(jewelry3);
list.add(jewelry4);
list.add(jewelry5);
list.add(jewelry6);
list.add(jewelry7);
while (list.size() > 1) {
//排序
Collections.sort(list);
//获取最小的两个
jewelry jewelryLeft = list.get(0);
jewelry jewelryRight = list.get(1);
//融合成玛瑙珠宝
jewelry root = new jewelry(jewelryLeft.value + jewelryRight.value);
root.leftJewelry = jewelryLeft;
root.rightJewelry = jewelryRight;
//去除掉原来最小的两颗珠宝
list.remove(jewelryLeft);
list.remove(jewelryRight);
//把玛瑙塞进去
list.add(root);
}
// 前序遍历查看
jewelry.traversal(list.get(0));
}
}
//想用Collections.sort()排序 该接口必须要实现
class jewelry implements Comparable<jewelry>{
jewelry leftJewelry;
jewelry rightJewelry;
int value;
public jewelry(int value){
this.value = value;
}
@Override
public String toString() {
return "jewelry{" +
"value=" + value +
'}';
}
@Override
public int compareTo(jewelry o) {
//从小到大排序,因为如果返回的是负数,说明o比this小,那么就把o放在this前面
return this.value - o.value;
}
//前序遍历查看 有没有写错
public static void traversal(jewelry root){
System.out.println(root);
if (root.leftJewelry != null)
traversal(root.leftJewelry);
if (root.rightJewelry != null)
traversal(root.rightJewelry);
}
}
通过上面的哈夫曼树,我们就可以对每个结点进行编码了;
即:规定从左边走0,从右边走为1,
这样 12的编码就是:001;3:0000;56: 1;10: 0001; 32: 01;
同时我们可以发现:任意一个数字的编码 都不是其他数字编码的前缀,这个特点尤其重要,因为可以避免混淆;
举一个反例: 假设 数字3的编码为:001 ;数字5的编码为:0010, 那么当读取当001的时候我们不知道是否读到这里就停止,还是继续读下去,这样就会造成问题;而哈夫曼编码就避免了这个问题