注意: 编码来自, 数的路径,规则是左子树的路径为0 右子树路径为1,数据存储在叶节点上,由于每个叶节点的路径是唯一的,(二叉平衡树的特点每个叶节点路径是唯一的)
构建过成:先从最小的开始相加 用倒数第一次小于倒数第二小的数字相加得到父节点
package com.jvm.peng;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created by 86178 on 2019/7/7.
*/
public class HuffmanTree {
//1 节点
public static class Node<E> {
E data; //数据
int weight; //权重
Node leftChild;
Node rightChild;
public Node(E data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public String toString() {
return "Node[" + weight + ",data=" + data + "]";
}
}
//2 构造哈夫曼树
//入参的list 中放入的是一个个的节点
public static Node createTree(List<Node> nodelist){
//因为每次都是把权重最小的两个合并,当类表合并完成那么只剩下一个根节点就代表结束
while(nodelist.size()>1) {
//对节点根据权重数进行排序 从小到大的排序 (使用冒泡排序之后用collections.sort 再试下)
// sout(nodelist); //冒泡排序
//使用工具类对 list 容器中的节点按照节点属性排序
Collections.sort(nodelist,new Comparator<Node>(){
@Override
public int compare(Node o1, Node o2) {
// System.out.println("进入 compare function");
// 如果后一个节点小于前一个节点则返回小于0的数表示互换 即从权重数小到大排序
if (o1.weight < o2.weight) {//o1属性小于等于o2属性时,返回-1 从小到大排序
return -1;
} else {
return 1;
}
}
});
//生成左节点与右节点
Node leftChild = nodelist.get(0);
Node rightChild = nodelist.get(1);
//生成父节点
Node parentNode = new Node(null,leftChild.weight+rightChild.weight);
parentNode.leftChild = leftChild;
parentNode.rightChild = rightChild;
//要把最小的两个都删除,并且把新生成的父节点放进类表
nodelist.remove(0);
nodelist.remove(0);
nodelist.add(parentNode);
}
//当所合并成到最后一个根节点,即一个树的时候返回出去
return nodelist.get(0);
}
// 冒泡排序下
private static void sout(List<Node> nodelist) {
if(nodelist.size()<=1){
return;
}
for(int i= 0;i<nodelist.size();i++){
for(int j = 0;j<nodelist.size()-i-1;j++){
//根基权重的值来去比较大小 如果后节点小于前节点权重则互换位置,即从小到大升序排列
if(nodelist.get(j+1).weight < nodelist.get(j).weight){
Node temp = nodelist.get(j+1);
nodelist.set(j+1,nodelist.get(j));
nodelist.set(j,temp);
}
}
}
}
public static void main(String[] args) {
ArrayList<Node> nodes = new ArrayList<>();
nodes.add(new Node("a", 10));
nodes.add(new Node("b", 15));
nodes.add(new Node("c", 12));
nodes.add(new Node("d", 3));
nodes.add(new Node("e", 4));
nodes.add(new Node("f", 13));
nodes.add(new Node("g", 1));
Node tree = HuffmanTree.createTree(nodes);
printTree(tree);
}
private static void printTree(Node tree) {
System.out.println(tree.toString());
if(tree.leftChild !=null){
System.out.print("left:");
printTree(tree.leftChild);
}
if(tree.rightChild !=null){
System.out.print("right:");
printTree(tree.rightChild);
}
}
}
compare 比较规则
if (o1.weight < o2.weight)
表示后一项小于前一项则进行交换 与冒泡排序类似可参考上面的冒牌排序
当compare的返回值小于0时,会将 t1 和 t2 (compare()中的两个参数)交换顺序,大于等于0不会变换顺序;
可根据具体的排序需求来决定是否让他们交换顺序