当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。 在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。在图 1 中,因为结点 a 的权值最大,所以理应直接作为根结点的孩子结点。
如下图就是:
关键词
路径:在一棵树中,一个结点到另一个结点之间的通路,称为路径。 路径长度:在一条路径中,每经过一个结点,路径长度都要加 1 。例如在一棵树中,规定根结点所在层数为1层,那么从根结点到第 i 层结点的路径长度为 i - 1 。 结点的权:给每一个结点赋予一个新的数值,被称为这个结点的权。 结点的带权路径长度:指的是从根结点到该结点之间的路径长度与该结点的权的乘积。 WPL:树的带权路径长度为树中所有叶子结点的带权路径长度之和。
构建最优二叉树
对于给定的有各自权值的 n 个结点: 1.在 n 个权值中选出两个最小的权值,对应的两个结点组成一个新的结点,两个结点作为新结点的孩子,且新的结点权值为左右孩子权值的和。 2.在原有的 n 个结点中删除那两个最小的权值,同时将新的结点加入到 n–2 个权值的行列中,以此类推。 3.重复 1 和 2 ,直到所以的结点构建成了一棵二叉树为止,这棵树就是哈夫曼树。
public static void main(String[] args) { HuffmanTree tree = new HuffmanTree(); Integer[] array = {1,5,3,2,7,9,6,4,8,15,10,12,13,11,14}; Node root = tree.createTree(array); tree.inTraverse(root); }
public Node createTree(Integer[] array){ if (array == null || array.length == 0){ return null; } List<Node> nodeList = new ArrayList<>(); Node node; for (Integer item : array){ node = new Node(); node.value = item; nodeList.add(node); } while (nodeList.size()>1){ Collections.sort(nodeList); Node newNode = new Node(); newNode.leftChild = nodeList.get(0); newNode.rightChild = nodeList.get(1); newNode.value = nodeList.get(0).value + nodeList.get(1).value; nodeList.remove(0); nodeList.remove(0); nodeList.add(newNode); } return nodeList.get(0); }
public void inTraverse(Node node){ System.out.println(node.value); if (node.leftChild!=null){ inTraverse(node.leftChild); } if (node.rightChild!=null){ inTraverse(node.rightChild); } }
class Node implements Comparable<Node>{
Integer value; Node leftChild; Node rightChild;
@Override public int compareTo(Node o) { return this.value - o.value; }
@Override public String toString() { return "node="+this.value; } } }
近期评论