引子:  这里的哈夫曼树的建立方法和上一篇不一样,是把数据放在数组上面的,而不是链表上面。因此,采用这种方法建立的哈夫曼树对节点的操作上比链式的哈夫曼树简单很多。对于空间问题,如果有m个item,那么需要建立2*m长度的数组,具体解释请看下面注释!

package tree;

import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.Set;

import tree.ListHuffManTree.Node;

public class ListHuffManTreeTest {

   public static void main(String[] args) {      ListHuffManTree t = new ListHuffManTree(26);     t.add(4, "A");      t.add(6, "E");      t.add(1, "C");      t.add(8, "D");      t.add(3, "U");      t.add(5, "P");      t.add(7, "B");      t.add(93, "F");     t.add(45, "G");     t.add(34, "H");     t.add(12, "I");     t.add(34, "K");     t.add(22,"O");      t.add(23, "L");     //创建哈夫曼树      t.createHuffmanTree();

      t.print();        //建立哈夫曼编码表        t.buildCodeTable();

      t.printCode();        //编码字符串hellogoogle        List<String> codeList = t.encode("HELLOGOOLE");      //解码      List<String> decodeList = t.decode(codeList);

      System.out.println();     System.out.print("解码: ");        for(String s: decodeList){            System.out.print(s);      }     System.out.println(); }}class ListHuffManTree{

  private Node[] nodes = null; //实际的叶子数  private int size; //最多的叶子数  private int maxSize;  //保存编码和源码,其中key为源码 Map<String,List<String>> codeMap = null;

  public ListHuffManTree(int maxSize){      this.maxSize = maxSize;      this.size = 0;       //叶子有maxSize个,则非叶子有maxSize-1个,因为第一个没用,所以有2*maxSize个      nodes = new Node[2*maxSize];

      codeMap = new HashMap<>(); }

  public boolean isFull(){      return size == maxSize;     }

  public void add(int weight, String item){     size++;     nodes[size] = new Node(weight, item);    }

  /**    * 选择权重最小的两个节点     * @return    */   private List<Integer> select(){     List<Integer> list = new ArrayList<Integer>();

      int index1 = -1;     int index2 = -1;

      int temp = Integer.MAX_VALUE;        int i = 1;       for(; i <= size; i++){          if(nodes[i].parent == 0 && temp > nodes[i].weight){              temp = nodes[i].weight;              index1 = i;          }     }     if(temp != Integer.MAX_VALUE){           nodes[index1].parent = -1;           list.add(index1);     }

      temp = Integer.MAX_VALUE;        int k = 1;       for(; k <= size; k++){          if(nodes[k].parent == 0 && temp > nodes[k].weight){              temp = nodes[k].weight;              index2 = k;          }     }     if(temp != Integer.MAX_VALUE){           nodes[index2].parent = -1;           list.add(index2);     }     return list;  }

  /**    * 建立哈夫曼树  */   public void createHuffmanTree(){      int tempSize = this.size;        for(int i = 0; i < tempSize; i++){          //选择权值最小的两个节点         List<Integer> list = select();         if(list.size() == 2){               int index1 = list.get(0);                int index2 = list.get(1);

              int w1 = nodes[index1].weight;               int w2 = nodes[index2].weight;

              //合并节点的权重             add(w1+w2, null);                nodes[size].lchild = index1;             nodes[size].rchild = index2;

              //改变父节点的index             nodes[index1].parent = size;             nodes[index2].parent = size;         }     } }

  /**    * 打印节点的详细信息   */   public void print(){      Node node = null;        for(int i = 1; i <= this.size; i++){           node = nodes[i];         System.out.println("item:"+node.item+" ;weight:"+node.weight+" ;parent:"+node.parent+" ;lchild:"+node.lchild+" ;rchild:"+node.rchild);     } }

  /**    * 建立编码表   * 思路:从每一个叶子节点依次到根节点,是父节点的左孩子,则为0,否则为1     */   public void buildCodeTable(){     for(int i = 1; i <= size; i++){            Node node = nodes[i];            //是否为叶子节点         if(node.lchild == 0 || node.rchild == 0){             //用来存储01信息,顺序和实际的相反                List<String> list = new ArrayList<>();

              String tempKey = nodes[i].item;

              int tempInt = i;             while(node.parent > 0){                    int p = node.parent;                 if(tempInt == nodes[p].lchild){                     list.add("0");                  }else{                        list.add("1");                  }                 node = nodes[p];                 tempInt = p;             }             codeMap.put(tempKey, list);           }     } }

  /**    * 打印二进制编码     */   public void printCode(){      Set<Entry<String,List<String>>> set = codeMap.entrySet();      Iterator<Entry<String,List<String>>> iter = set.iterator();        while(iter.hasNext()){            Entry<String,List<String>> entry = iter.next();          System.out.print(entry.getKey()+": ");         List<String> list = entry.getValue();          for(int i = list.size()-1; i >= 0; i--){             System.out.print(list.get(i));            }         System.out.println();     } }

  public List<String> encode(String target){      System.out.print(target+" 的编码: ");

      List<String> li = new ArrayList<String>();

      int len = target.length();       for(int i = 0; i < len; i++){           String temp = String.valueOf(target.charAt(i));          List<String> list = codeMap.get(temp);         for(int k = list.size()-1; k >= 0; k--){             System.out.print(list.get(k));                li.add(list.get(k));          }     }     return li;    }

  /**    * 解码  * @param codeList 二进制编码  * @return 解码结果   */   public List<String> decode(List<String> codeList){

      List<String> list = new ArrayList<String>();

      int tempSize = size;     for(String s : codeList){         if("0".equals(s)){              int lch = nodes[tempSize].lchild;                String itemString = nodes[lch].item;             if(itemString != null){                  list.add(itemString);                 tempSize = size;                 continue;             }             tempSize = lch;          }else if("1".equals(s)){                int rch = nodes[tempSize].rchild;                String itemString = nodes[rch].item;             if(itemString != null){                  list.add(itemString);                 tempSize = size;                 continue;             }             tempSize = rch;          }     }     return list;  }

  /**    * 节点  * @author LiangYH    *     */   class Node{       //parent index        int parent;       //left child index        int lchild;       //right child index       int rchild;       //rate        int weight;       //        String item;

      public Node(){            this.item = null;            this.lchild = 0;         this.rchild = 0;         this.parent = 0;         this.weight = -1;        }

      public Node(int weight, String item){         this.weight = weight;            this.item = item;            this.parent = 0;         this.lchild = 0;         this.rchild = 0;     } }}

结果:

思考:
上面选择权值最小的两个节点的方法不是特别理想,如何改进?

哈夫曼树--顺序结构(建立、编码、解码)相关推荐

  1. 哈夫曼树的构建、编码以及带权路径长计算

    给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较 ...

  2. 【id:179】【20分】C. DS二叉树--赫夫曼树的构建与编码(不含代码框架)

    题目描述 给定n个权值,根据这些权值构造huffman树,并进行huffman编码 参考课本P147算法6.12 HuffmanCoding代码,注意数组访问是从位置1开始 要求:赫夫曼的构建中,默认 ...

  3. c语言最优树的构造,哈夫曼树的构造及编码 Haffman树的构造及其编码

    写出构造完整的哈夫曼树的编码 void HuffmanCoding(HuffmanCode HC[], int w[], int n) // w存放n个字符的权值(均>0),构造哈夫曼树HT, ...

  4. 哈夫曼树原理及Java编码实现

    文章目录 前言 一.哈夫曼树原理 二.哈夫曼编码(Java题解) 参考资料 前言 所有博客文件目录索引:博客目录索引(持续更新) 源代码:Gitee-Huffman.java.Github-Huffm ...

  5. 赫夫曼树的经典应用——赫夫曼编码解码

    之前利用赫夫曼树来对字符串进行压缩,相当于对字符串加密.现在需要利用赫夫曼编码来进行解码,也就是解密. 如果还不了解赫夫曼编码的小伙伴可以先看上篇文章--利用哈夫曼树实现哈夫曼编码进行字符串压缩 之前 ...

  6. PTA 哈夫曼树与哈夫曼编码

    输入格式: 输入有3行. 第1行:符号个数n(2-20). 第2行:一个不含空格的字符串.记录着本题的符号表.我们约定符号都是单个的小写英文字母,且从字符'a'开始顺序出现.也就是说,如果 n 为 2 ...

  7. 霍夫曼树:霍夫曼编码(Huffman Tree:Huffman Coding)

    一.简介 霍夫曼树常处理符号编写工作.根据整组数据中符号出现的频率高低,决定如何给符号编码.如果符号出现的频率越高,则给符号的码越短,相反符号的号码越长. 相关术语 路径:从书中一个节点到另一个节点之 ...

  8. 赫夫曼树建立c语言源程序编译结果详细解释,哈夫曼树的建立与实现最终版(备份存档)...

    <哈夫曼树的建立与实现.doc>由会员分享,可免费在线阅读全文,更多与<哈夫曼树的建立与实现(最终版)>相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索 ...

  9. 赫夫曼树建立c语言源程序编译结果详细解释,c语言构建哈夫曼树(附运行结果图)[本站推荐]...

    #include#include#include int m,s1,s2; typedef struct { unsigned int weight; unsigned int parent,lchi ...

最新文章

  1. 机器学习模型质量评价标准 — 精准率、召回率
  2. jquery java json转字符串_用jQuery以及JSON包将表单数据转为JSON字符串
  3. java 大端字节序_理解字节序 大端字节序和小端字节序
  4. 【机器视觉】 dev_clear_obj算子
  5. LeakCanary——直白的展现Android中的内存泄露
  6. 用PHP实现POP3邮件的收取(一)
  7. mysql error 变量_mysql 变量问题
  8. leetcode1267. 统计参与通信的服务器(dfs)
  9. 排序——宇宙总统(洛谷 P1781)
  10. 数魔选品怎么样_Sellermotor数魔跨境好不好用?怎么样?
  11. java awt编程_java awt编程
  12. plsql登录,tables表为空解决方案
  13. html中半圆怎么写,html 中画半圆的方法
  14. Springboot属性配置绑定
  15. 信息系统项目管理--论文分析笔记
  16. IDEA 代码格式化
  17. AXI 总线基本概念 - 如何理解outstanding传输
  18. linux终端联网网速慢,解决ubuntu 上网速度慢的问题
  19. [026] 微信公众帐号开发教程第2篇-微信公众帐号的类型(普通和会议)
  20. 跳石头 解题报告【二分答案】

热门文章

  1. oracle字典表导出,oracle 如何导出数据字典
  2. python flask表单语法_Flask框架如何使用表单
  3. 使用指针判断数组是否为上三角矩阵
  4. 【c语言】hello
  5. jsp是在html中添加什么作用域,JSP九个内置对象 四大作用域 动作指令
  6. java游戏下载ios_java浏览器下载
  7. Nodejs教程30(完结):PM2入门
  8. 敏捷个人2012.8月份线下活动报道:Toastmasters、团队管理
  9. Python 列表 insert() 方法
  10. Python学习(10)元组