赫夫曼树:是一个权值最大的结点离根结点最近的优化树
权值就是每个结点的值
路径是通过一个结点往下可以达到孩子或孙子结点之间的通路
树的带权路径长度是所有叶子结点的带权路径长度与该结点的乘积 记为WPL
WPL最小的就是赫夫曼树
权值最大的结点距离根结点最近的二叉树是最右二叉树
从根结点到E的路径长度就是E结点的层数减去根结点的层数就是路径长度
E的带权路径长度就是它的路劲长度*E的权值=E的带权路径长度
假设把13,7,8,29,6,1组成一个赫夫曼树的各个结点的权值
首先需要把这些数做一个排序然后取出最小的两个结点
这最小的两个结点之和作为这个结点的父结点
重复步骤就可以组成一个赫夫曼树
最终树的结构就是:
创建二叉树:
/**
* 实现Comparable借口 方便排序结点的权值
*/
public class node implements Comparable<node> {
/*
创建树的结点
id表示树的权值
left right左右子树
*/
private int id;
private node left;
private node right;
/*
前序遍历二叉树
*/
public void preSelect(){
System.out.println(this);
if(this.getLeft()!=null) this.getLeft().preSelect();
if(this.getRight()!=null) this.getRight().preSelect();
}
public node(int id) {this.id = id;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public node getLeft() {return left;}
public void setLeft(node left) {this.left = left;}
public node getRight() {return right;}
public void setRight(node right) {this.right = right;}
@Override
public String toString() {return "node{" + "id=" + id + '}';}
/*
实现排序
此结点的权值减去对比结点的权值
大于返回1或以上
等于返回0
小于返回负数
*/
@Override
public int compareTo(node o) {return this.id-o.id;}
}
将普通二叉树转为赫夫曼树:
/**
* 赫夫曼树的转化操作及创建
*/
public class HuffmanTree {
/**
* 传进来是需要转换的数组每个元素就是权值
* 返回的一定是根结点
* @param array
* @return
*/
public node HuffmanChange(int[] array){
/*
创建集合存放结点
*/
List<node> nodes = new ArrayList<node>();
/*
集合的每个结点以数组的元素创建到集合中去
*/
for(int i:array){
nodes.add(new node(i));
}
/*
1,集合排序Collections.sort
2,取出集合中权值最小的两个结点组成一个新的结点作为这两个结点的父结点
3,既然集合中最小的两位数已经用过了就把他们删除
4,将新的结点放到集合中来进行下一轮的排序迭代创建新结点
*/
while(nodes.size()>1){
Collections.sort(nodes);
node leftNode = nodes.get(0);
node rightNode = nodes.get(1);
node newNode = new node(leftNode.getId()+rightNode.getId());
newNode.setLeft(leftNode);
newNode.setRight(rightNode);
nodes.remove(0);
nodes.remove(0);
nodes.add(newNode);
}
//集合中一定会剩下一个元素因为nodes.size()>1的条件限制
//也是最后两个数的父结点也就是最后的根结点
System.out.println(nodes.size());
/*
返回集合中仅剩的元素
*/
return nodes.get(0);
}
}