1. 基本介绍:

二叉树
给定13, 7, 8, 3这四个数作为叶子结点,构建成二叉树,部分情况如下:

二叉树
这种情况,权值为 2 * 13 + 2 * 7 + 2 * 8 + 2 * 3 = 62。

二叉树
这种情况,权值为1 * 13 + 2 * 8 + 3 * 7 + 3 * 3 = 59。
显然第二种情况权值更小,确保没有更小的情况下,这棵二叉树就叫做赫夫曼树。
2. 构建赫夫曼树:
假如现在要将13, 7, 8, 3, 29, 6, 1构建成赫夫曼树,步骤如下:
1, 3, 6, 7, 8,13, 29。1和3,构建出如下二叉树:
第一步
1和3就已经用掉了,将上一步构建的二叉树的根节点4放入数组中排序,结果就是:4, 6, 7, 8, 13, 29。4和6,构建成一棵二叉树,如下图:
第二步
10放到序列中,此时的序列就是这样的:7, 8, 10, 13, 29。7和8,构建二叉树,如下:
第三步
15放到序列中,此时序列就变成了:10, 13, 15, 29,并且此时构建出了两棵二叉树,还没关联起来,先不用急。10和13,构建成二叉树,此时二叉树就变成了:
第四步
23放到序列中,序列就变成了:15, 23, 29。15和23,构建成二叉树,15和23是两棵树的根节点,经过这一步,两棵树就合并了:
第五步
29和38了,所以将29加到这棵树上就好了,如下图:
第六步
3. 代码实现:
/**
* 赫夫曼树
* @author zhu
*
*/
public class HuffmanTree {
/**
* 构建赫夫曼树
* @param arr
* @return
*/
public static Node buildHufmanTree(int[] arr) {
// 将数组转成集合,方便增删元素
List<Node> nodes = new ArrayList<>();
for (int i=0; i<arr.length; i++) {
nodes.add(new Node(arr[i]));
}
// 对集合进行排序
Collections.sort(nodes);
// 循环构建
while (nodes.size() > 1) {
// 取出前两个节点,构建二叉树
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parentNode = new Node(leftNode.getValue() + rightNode.getValue());
parentNode.setLeft(leftNode);
parentNode.setRight(rightNode);
// 移除用掉了的元素,将parent的值添加进集合
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parentNode);
// 重新排序
Collections.sort(nodes);
}
// 返回赫夫曼树的根节点
return nodes.get(0);
}
/**
* 前序遍历
*
* @param root
*/
public static void preOrder(Node root) {
// 先输出当前节点
System.out.println(root.getValue());
// 判断左子节点是否为空,不为空就递归
if (root.getLeft() != null) {
preOrder(root.getLeft());
}
// 判断右子节点是否为空,不为空就递归
if (root.getRight() != null) {
preOrder(root.getRight());
}
}
/**
* 节点内部类,实现compareble接口,方便对node排序
* @author zhu
*
*/
static class Node implements Comparable<Node>{
private int value;
private Node left;
private Node right;
public Node(int val) {
this.value = val;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
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 [value=" + value + "]";
}
@Override
public int compareTo(Node o) {
// 升序
return this.value - o.value;
}
}
public static void main(String[] args) {
int[] arr = {13, 7, 8, 3, 29, 6, 1};
Node node = buildHufmanTree(arr);
preOrder(node);
}
}上面是创建赫夫曼树的完整代码,构件好之后,用前序遍历方法遍历一下,然后看看与上面图中的赫夫曼树前序遍历结果是否一致,如果一致,表示构建成功。