import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* 哈夫曼树
*
* @author PengHao
* @date 2020-03-24 22:21
*/
public class HuffmanTree {
/**
* 哈夫曼树的根结点
*/
private Node root;
/**
* 带权路径长度(Weighted Path Length)
*/
private int wpl;
/**
* 构造方法
*
* @param values 用于构造哈夫曼树的数据数组
*/
public HuffmanTree(int[] values) {
int[] a = Arrays.copyOf(values, values.length);
// 根据数组a创建哈夫曼树
root = createHuffmanTree(a);
}
/**
* 创建哈夫曼树
*
* @param values 用于构造哈夫曼树的数据数组
*/
private Node createHuffmanTree(int[] values) {
Queue<Node> queue = new PriorityQueue<>();
// 将数据封装成结点并添加到优先队列中
for (int value : values) {
queue.offer(new Node(value));
}
// 将2个结点合并成一个结点
while (queue.size() > 1) {
Node left = queue.poll();
Node right = queue.poll();
Node father = new Node(left.value + right.value);
father.leftChild = left;
father.rightChild = right;
queue.offer(father);
}
// 最后的结点就是根结点
return queue.poll();
}
/**
* 计算WPL
*
* @param root 当前子树的根结点
* @param level 当前子树根结点的层数,整个哈夫曼树的根结点层数为0
* @return 当前子树的带权路径长度
*/
private int setWPL(Node root, int level) {
if (root.leftChild == null && root.rightChild == null) {
return root.value * level;
}
int leftWPL = setWPL(root.leftChild, level + 1);
int rightWPL = setWPL(root.rightChild, level + 1);
return leftWPL + rightWPL;
}
/**
* 获取带权路径长度,如果wpl为0,则计算wpl,否则
*
* @return 带权路径长度
*/
public int getWPL() {
if (wpl == 0) {
wpl = setWPL(root, 0);
}
return wpl;
}
/**
* 二叉树结点
*
* @author PengHao
* @date 2020-03-24 22:06
*/
private class Node implements Comparable<Node> {
int value;
Node leftChild;
Node rightChild;
public Node(int value) {
this.value = value;
}
@Override
public int compareTo(Node o) {
// 按照权重升序排序
return value - o.value;
}
}
}
Test结果为:30
public class Test {
public static void main(String[] args) {
HuffmanTree huffmanTree = new HuffmanTree(new int[]{5, 8, 1, 3});
System.out.println(huffmanTree.getWPL());
}
}