赫夫曼树
一、基本介绍
1、给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这 样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree), 还有的书翻译为霍夫曼树。
2、赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
二、重要概念
1、路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1
2、结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积
3、树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL(weighted path length) ,权值越大的结点离根结点越近的二叉树才是最优二叉树。
4、WPL最小的就是赫夫曼树
三、代码
1 public class HuffmanTree { 2 3 public static void main(String[] args) { 4 int arr[] = { 13, 7, 8, 3, 29, 6, 1 }; 5 Node root = createHuffmanTree(arr); 6 7 preOrder(root); 8 } 9 public static void preOrder(Node root){ 10 if(root!=null){ 11 root.preOrder(); 12 }else { 13 System.out.println("空数"); 14 } 15 } 16 17 // 创建赫夫曼树的方法 18 /** 19 * @param arr 需要创建成哈夫曼树的数组 20 * @return 创建好后的赫夫曼树的root结点 21 */ 22 public static Node createHuffmanTree(int[] arr){ 23 // 第一步为了操作方便 24 // 1. 遍历 arr 数组 25 // 2. 将arr的每个元素构成成一个Node 26 // 3. 将Node 放入到ArrayList中 27 ArrayList<Node> nodes = new ArrayList<>(arr.length); 28 for (int v : arr) { 29 nodes.add(new Node(v)); 30 } 31 //我们处理的过程是一个循环的过程 32 while (nodes.size()>1){ 33 //排序 从小到大 34 Collections.sort(nodes); 35 System.out.println(nodes); 36 //取出根节点权值最小的两颗二叉树 37 //(1) 取出权值最小的结点(二叉树) 38 Node l = nodes.get(0); 39 //(2) 取出权值第二小的结点(二叉树) 40 Node r = nodes.get(1); 41 //(3)构建一颗新的二叉树 42 Node parent = new Node(l.value + r.value); 43 parent.left = l; 44 parent.right = r; 45 //(4)从ArrayList删除处理过的二叉树 46 nodes.remove(l); 47 nodes.remove(r); 48 //(5)将parent加入到nodes 49 nodes.add(parent); 50 } 51 //返回哈夫曼树的root结点 52 return nodes.get(0); 53 } 54 } 55 // 创建结点类 56 // 为了让Node 对象持续排序Collections集合排序 57 // 让Node 实现Comparable接口 58 class Node implements Comparable<Node>{ 59 int value;// 结点权值 60 char c; 61 Node left; 62 Node right; 63 //写一个前序遍历 64 public void preOrder(){ 65 System.out.println(this); 66 if(this.left!=null){ 67 this.left.preOrder(); 68 } 69 if(this.right!=null){ 70 this.right.preOrder(); 71 } 72 } 73 @Override 74 public String toString() { 75 return "Node{" + 76 "value=" + value + 77 '}'; 78 } 79 80 public Node(int value) { 81 this.value = value; 82 } 83 84 @Override 85 public int compareTo(Node o) { 86 return 0; 87 } 88 }