最终结果哈夫曼树,如图所示:

直接上代码:

  1. public class HuffmanCode {
  2. public static void main(String[] args) {
  3. //获取哈夫曼树并显示
  4. Hnode root = createHuffmanTree(createNodes());
  5. root.beforePrint();
  6. System.out.println("====================");
  7. //从哈夫曼树中读取 哈夫曼编码
  8. getHuffmanCode(root);
  9. //从huffmanCodes 中读取哈夫曼编码:A:10, B:01, C:0011,D:11,E:000,F:00100,G:00101
  10. System.out.println("哈夫曼编码为:"+huffmanCodes);
  11. }
  12. //创建一个 Hnode节点的集合
  13. public static List<Hnode> createNodes(){
  14. List<Hnode> nodes = new ArrayList<Hnode>();
  15. nodes.add(new Hnode(new Person(12,"A"),60));
  16. nodes.add(new Hnode(new Person(13,"B"),45));
  17. nodes.add(new Hnode(new Person(14,"C"),13));
  18. nodes.add(new Hnode(new Person(15,"D"),69));
  19. nodes.add(new Hnode(new Person(16,"E"),14));
  20. nodes.add(new Hnode(new Person(17,"F"),5));
  21. nodes.add(new Hnode(new Person(18,"G"),3));
  22. return nodes;
  23. }
  24. //根据list 创建哈夫曼树
  25. public static Hnode createHuffmanTree(List<Hnode> nodes){
  26. while(nodes.size() > 1){
  27. //先对 nodes进行从小到大排序, 根据权重值进行从小到大排序
  28. Collections.sort(nodes, new Comparator<Hnode>() {
  29. public int compare(Hnode o1, Hnode o2) {
  30. return o1.weight - o2.weight;
  31. }
  32. });
  33. //取出前二个最小的元素,构建一个父节点只有权重 没有数据的二叉树
  34. Hnode leftNode = nodes.get(0);
  35. Hnode rightNode = nodes.get(1);
  36. Hnode parent = new Hnode(null, leftNode.weight + rightNode.weight);
  37. parent.leftNode = leftNode;
  38. parent.rightNode = rightNode;
  39. //将原来nodes中已经处理的前二个最小元素删除调,并将parent节点存入nodes中
  40. nodes.remove(leftNode);
  41. nodes.remove(rightNode);
  42. nodes.add(parent);
  43. }
  44. //循环结束时候,nodes中只有一个节点了,且该节点就是哈夫曼树的根节点
  45. return nodes.get(0);
  46. }
  47. static StringBuilder stringBuilder = new StringBuilder();
  48. static Map<String,String> huffmanCodes = new HashMap<String, String>();
  49. //从哈夫曼树中读取 哈夫曼编码: A:10, B:01, C:0011,D:11,E:000,F:00100,G:00101
  50. public static void getHuffmanCode(Hnode root){
  51. if (root == null) {
  52. return ;
  53. }
  54. getCode(root.leftNode,"0",stringBuilder);
  55. getCode(root.rightNode,"1",stringBuilder);
  56. }
  57. private static void getCode(Hnode node, String code, StringBuilder builder) {
  58. StringBuilder builder1 = new StringBuilder(builder);
  59. builder1.append(code);
  60. if (node != null) {
  61. if (node.person == null) {
  62. //如果数据为不null,说明是子节点
  63. //左递归处理
  64. getCode(node.leftNode,"0",builder1);
  65. //右递归处理
  66. getCode(node.rightNode,"1",builder1);
  67. }else{
  68. //如果数据为null,说明是叶子节点
  69. huffmanCodes.put(node.person.name,builder1.toString());
  70. }
  71. }
  72. }
  73. }
  74. //先建节点
  75. class Hnode{
  76. Person person;//数据
  77. int weight;//权重
  78. Hnode leftNode;
  79. Hnode rightNode;
  80. public Hnode(Person person, int weight) {
  81. this.person = person;
  82. this.weight = weight;
  83. }
  84. @Override
  85. public String toString() {
  86. return "Hnode{" +
  87. "data='" + person + '\'' +
  88. ", weight=" + weight +
  89. '}';
  90. }
  91. //前序遍历
  92. public void beforePrint(){
  93. System.out.println(this);
  94. if (this.leftNode != null) {
  95. this.leftNode.beforePrint();
  96. }
  97. if (this.rightNode != null) {
  98. this.rightNode.beforePrint();
  99. }
  100. }
  101. }
  102. class Person {
  103. int age;
  104. String name;
  105. public Person(int age, String name) {
  106. this.age = age;
  107. this.name = name;
  108. }
  109. @Override
  110. public String toString() {
  111. return "Person{" +
  112. "age=" + age +
  113. ", name='" + name + '\'' +
  114. '}';
  115. }
  116. }

结果如下:

压缩原理:

1: 被压缩文件通过输入流,转化为原始字节数组, 遍历统计每个字节出现的次数,并转化为map, key:字节,value:该字节的次数

2: map 转化为list,根据list创建 哈夫曼树,并获取到对应的哈夫曼编码

3: 将哈夫曼编码转化字节数组,通过输出流,写入到目标文件中,同时将哈夫曼编码也写入到目标文件中(目的:是为了解码使用)

解压缩原理:

1: 通过输入流从被解压缩文件中,读取到哈夫曼编码,和 哈夫曼编码转化字节数组,

2: 解码 得到原始字节数组, 并将数组写出到目标文件中

10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压的更多相关文章

  1. Java数据结构和算法(七)B+ 树

    Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...

  2. java 文件压缩和解压(ZipInputStream, ZipOutputStream)

    最近在看java se 的IO 部分 , 看到 java 的文件的压缩和解压比较有意思,主要用到了两个IO流-ZipInputStream, ZipOutputStream,不仅可以对文件进行压缩,还 ...

  3. java文件压缩和解压

    功能实现. package com.test; import java.io.File; import java.io.BufferedOutputStream; import java.io.Buf ...

  4. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

  5. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

  6. 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现

      本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型   栈是 ...

  7. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

  8. java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...

  9. Java数据结构和算法 - 高级排序

    希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...

随机推荐

  1. nodejs-REPL/回调函数/事件循环

    REPL 回调函数 事件循环 REPL----------------------------------------------------- Node.js REPL(Read Eval Prin ...

  2. 每天一道面试题LeetCode 80--删除排序数组中的重复项 II(python实现)

    LeetCode 80--删除排序数组中的重复项 II 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输 ...

  3. @NotNull 、@NotBlank、@NotEmpty区别

    @NotNull: 主要用在基本数据类型上(Integer.Double...) 不能为null,但可以为empty 举例: @NotNull(message = "标题不能为空" ...

  4. TP之安全机制

    防止sql注入 1.查询条件尽量使用数组方式,具体如下: 1 $wheres = array(); 2 3 $wheres['account'] = $account; 4 5 $wheres['pa ...

  5. 『动善时』JMeter基础 — 15、使用JMeter实现上传文件

    目录 1.用于演示的项目说明 2.测试计划内包含的元件 3.HTTP请求界面内容 4.查看结果 5.总结 6.补充:MIME类型简介 (1)MIME说明 (2)常见类型 在上一篇文章[使用JMeter ...

  6. [Qt] Librecad 源码分析

    libraries jwwlib libdxfrw:一个免费的C++库,用于读写文本格式或二进制格式的DXF文件(C++ library to read and write DXF/DWG files ...

  7. 电脑无法开机,用一个U盘先备份C盘部分重要文件并重装Win10系统的教程?

    电脑无法开机,用一个U盘先备份C盘部分重要文件并重装Win10系统的教程.? 这应该是修电脑的万能方法,重装系统能解决绝大多数非硬件导致的电脑故障,但之前要备份一下桌面的一些个人文件.所以想学一下,以 ...

  8. 使用ps、top、ps_mem命令找出Linux中的最大内存消耗过程

    使用ps.top.ps_mem命令找出Linux中的最大内存消耗过程 2020-02-08 16:06:59作者:自力稿源:云网牛站 您可能已经看到Linux系统多次消耗过多的内存,如果是这种情况,那 ...

  9. Ansible流程控制

    Ansible流程控制 数据库操作问题: 数据库的操作问题,python需要依耐的模块MySQL-python . 数据库的操作 # 设置root的密码在,root的密码设置之后,创建用户和创建数据库 ...

  10. 012.Kubernetes的configmap和secret配置

    使用configmap对多有的配置文件进行统一管理 一 configmap配置管理 1.1 检查mysql的配置 [root@docker-server1 storage]# kubectl get ...