当前位置:主页 > 查看内容

Java编程内功-数据结构与算法「赫夫曼树」

发布时间:2021-04-18 00:00| 位朋友查看

简介:基本介绍 给定 n 个权值作为 n 个叶子节点,构造一颗二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也成为哈夫曼树(Huffman Tree),还有的书翻译成霍夫曼树。 赫夫曼树是带权路径长度最短的树,权值较大的节点离根很近。 几个重……

基本介绍

给定 n 个权值作为 n 个叶子节点,构造一颗二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也成为哈夫曼树(Huffman Tree),还有的书翻译成霍夫曼树。

赫夫曼树是带权路径长度最短的树,权值较大的节点离根很近。

几个重要概念

  1. **路径和路径长度:**在一颗树种,从一个节点往下可以达到的孩子或孙子节点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根节点的层数为1,则从根节点到L层节点的路径长度为:L-1.
  2. **节点的权和带权路径长度:**若将树种的节点赋给一个有某种含义的数值,则这个数值称为该节点的权。节点的带权路径长度为:从根节点到该节点之间的路径长度与该节点的权的乘积。
  3. 树的带权路径长度:树的带权路径长度规定为所有叶子节点的带权路径长度之和,即为WPL(weighted path length),权值越大的节点离根节点越近的二叉树才是最优二叉树。
  4. WPL最小的就是赫夫曼树

wpl=59的是赫夫曼树

赫夫曼树创建思路

给定一个数列{13,7,8,3,29,6,1},要求转成一个赫夫曼树

  1. 从小到大进行排序,将每一个数据都看成一个节点,每个节点可以看成是一颗最简单的二叉树。
  2. 取出根节点权值最小的两颗二叉树。
  3. 组成一颗新的二叉树,该新的二叉树的根节点的权值就是前面两个二叉树根节点权值的和。
  4. 再将这个新的二叉树,以根节点的权值大小排次排序,不断重复1-2-3-4的步骤,直到数列中,所有的数据都被处理,就得到一颗赫夫曼树。如下图所示:

代码案例

  1. package com.xie.huffmantree; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.Collections; 
  5. import java.util.List; 
  6.  
  7. public class HuffmanTree { 
  8.     public static void main(String[] args) { 
  9.         int[] arr = {13, 7, 8, 3, 29, 6, 1}; 
  10.         Node huffmanTree = createHuffmanTree(arr); 
  11.         //前序遍历 
  12.         preOrder(huffmanTree); 
  13.         /** 
  14.          * Node{value=67} 
  15.          * Node{value=29} 
  16.          * Node{value=38} 
  17.          * Node{value=15} 
  18.          * Node{value=7} 
  19.          * Node{value=8} 
  20.          * Node{value=23} 
  21.          * Node{value=10} 
  22.          * Node{value=4} 
  23.          * Node{value=1} 
  24.          * Node{value=3} 
  25.          * Node{value=6} 
  26.          * Node{value=13} 
  27.          */ 
  28.     } 
  29.  
  30.     //创建赫夫曼树 
  31.     public static Node createHuffmanTree(int[] arr) { 
  32.         //第一步为了操作方便 
  33.         //1.遍历 arr 数组 
  34.         //2.将 arr 的每个元素构成一个Node 
  35.         //3.将 Node 放入 ArrayList中 
  36.         List<Node> nodes = new ArrayList<>(); 
  37.         for (int value : arr) { 
  38.             nodes.add(new Node(value)); 
  39.         } 
  40.  
  41.         while (nodes.size() > 1) { 
  42.             //排序 从小到大 
  43.             Collections.sort(nodes); 
  44.             System.out.println("nodes = " + nodes); 
  45.  
  46.             //取出根节点权值最小的两颗二叉树 
  47.             //(1)取出权值最小的节点(二叉树) 
  48.             Node leftNode = nodes.get(0); 
  49.             //(2) 取出权值第二小的节点(二叉树) 
  50.             Node rightNode = nodes.get(1); 
  51.  
  52.             //(3) 构建一颗新的二叉树 
  53.             Node parent = new Node(leftNode.value + rightNode.value); 
  54.             parent.left = leftNode; 
  55.             parent.roght = rightNode; 
  56.  
  57.             //(4) 从ArrayList中删除处理过的二叉树 
  58.             nodes.remove(leftNode); 
  59.             nodes.remove(rightNode); 
  60.  
  61.             //(5) 将parent加入nodes 
  62.             nodes.add(parent); 
  63.         } 
  64.  
  65.         //返回赫夫曼树的root节点 
  66.         return nodes.get(0); 
  67.  
  68.     } 
  69.  
  70.     public static void preOrder(Node node) { 
  71.         if (node != null) { 
  72.             node.preOrder(); 
  73.         } else { 
  74.             System.out.println("是空树,不能遍历~~"); 
  75.         } 
  76.  
  77.     } 
  78.  
  79. //创建节点类,为了让Node对象支持排序,实现了Comparble接口 
  80. class Node implements Comparable<Node> { 
  81.     //权值 
  82.     int value; 
  83.     //指向左子节点 
  84.     Node left
  85.     //指向右子节点 
  86.     Node roght; 
  87.  
  88.     //写一个前序遍历 
  89.     public void preOrder() { 
  90.         System.out.println(this); 
  91.         if (this.left != null) { 
  92.             this.left.preOrder(); 
  93.         } 
  94.  
  95.         if (this.roght != null) { 
  96.             this.roght.preOrder(); 
  97.         } 
  98.     } 
  99.  
  100.     public Node(int value) { 
  101.         this.value = value; 
  102.     } 
  103.  
  104.     @Override 
  105.     public String toString() { 
  106.         return "Node{" + 
  107.                 "value=" + value + 
  108.                 '}'
  109.     } 
  110.  
  111.     @Override 
  112.     public int compareTo(Node o) { 
  113.         //从小到大进行排序 
  114.         return this.value - o.value; 
  115.     } 

本文转载自网络,原文链接:https://www.toutiao.com/i6935057608315470339/
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文

  • 周排行
  • 月排行
  • 总排行

随机推荐