文章目录

  • 一、浅谈赫夫曼编码
  • 二、获取赫夫曼编码
    • 1.获取字符出现的次数
    • 2.创建赫夫曼树
    • 3.指定编码
  • 三、代码实现
    • 1.指定编码代码
    • 2.完整代码
  • 总结

提示:以下是本篇文章正文内容,下面案例可供参考

一、浅谈赫夫曼编码

  赫夫曼编码(Huffman Coding),又称霍夫曼编码(哈夫曼编码),是一种编码方式,赫夫曼编码是可变字长编码(VLC)的一种。
  赫夫曼编码满足前缀编码,即某个字符的编码都不能是其他字符编码的前缀编码,因此不会造成匹配的多义性。

二、获取赫夫曼编码

赫夫曼编码一般用于通信领域中当作信息的一种处理方式 ,处理的规则如下
我们将不同的字符当成不同的节点,每个字符出现的次数作为该节点的权值,将所有节点构造成一个赫夫曼树 我的上一篇博客有提到赫夫曼树的创建(还请各位大佬斧正)link
形成赫夫曼树后,我们将二叉树的左路指定为0右路指定为1,沿赫夫曼树根节点到每个节点的路径保存相应的编码。

下面我们以字符串“hungryandhumble”为例

1.获取字符出现的次数

通过分析 各个字符出现的次数统计如下表1

表1 各个字符出现的次数

2.创建赫夫曼树

注意: 赫夫曼树根据排列的方法不同,也可能不太一样,这样对应的赫夫曼编码也不完全一样,但是赫夫曼树的带权路径长度WPL都是一样的,均为最小值。

例如 在上面的例子中,有多个字符出现的次数一样,当我们在森林中取出两棵树形成新树的过程中,由于有多个字符权值相同, 比如我们既可能取出字符r和字符y,也有可能取出字符a和字符b。同时,我们每次在森林中取出的两棵树摆放的位置也会影响赫夫曼树的生成,比如我们既可以将取出的字符r放在左边,将字符y放在右边,也可以反过来。

赫夫曼树(哈夫曼树)的创建(java实现)
视频演示赫夫曼树的生成过程

按照上述规则,创建的赫夫曼树如下

3.指定编码

我们将二叉树的左路指定为0,右路指定为1
效果图如下

沿赫夫曼树根节点到每个节点的路径保存相应的编码。
效果图如下

三、代码实现

1.指定编码代码

//获取赫夫曼编码 向左边路径为0  右边为1//思路//1.每个节点的赫夫曼编码保存到huffmanCodes中//2.生成赫夫曼编码的时候用到StringBuilder拼接路径static Map<Byte, String> huffmanCodes = new HashMap<>();static StringBuilder stringBuilder = new StringBuilder();/*** @param node 节点* @param code 代码编码的值 0 / 1* @param stringBuilder 用于拼接编码*/public static void getCodes(Node02 node, String code, StringBuilder stringBuilder) {StringBuilder temp = new StringBuilder(stringBuilder); //保存上次拼接的值temp.append(code); //拼接if (node != null) {if (node.getData() == null) { //node为非叶子节点getCodes(node.getLeft(), "0", temp); //向左递归遍历getCodes(node.getRight(), "1", temp); //向右递归遍历} else { //说明bide是叶子节点huffmanCodes.put(node.getData(), temp.toString()); //将相应的赫夫曼编码保存到Map中}}}

2.完整代码

package com.xx.huffmantree;import java.util.*;/*** @author 谢鑫* @version 1.0* @date 2021/12/10 10:41*/
public class HuffmanCode {public static void main(String[] args) {String str = "hungryandhumble";List<Node02> nodes = getNodes(str);System.out.println(nodes);Node02 root = createHuffmanTree(nodes);preOrder(root);//测试生成的赫夫曼编码getCodes(root, "", stringBuilder);System.out.println(huffmanCodes);}public static List<Node02> getNodes(String aString) {List<Node02> nodes = new ArrayList<>(); //用于存放节点byte[] contents = aString.getBytes();Map<Byte, Integer> map = new HashMap<>(); //Byte对象存放字符 Iterator对象存放字符出现的次数(权值)Integer count = null; //记录每个字符的权值for (byte element : contents) {count = map.get(element);if (count == null) { //如果map中不包含此元素map.put(element, 1); //则添加进map 并将权值设为1} else { //否则权值加1map.put(element, ++count);}}//将map中的数据新建节点添加到list中返回Set keySet = map.keySet(); //获取map的全部key值for (Object key_ : keySet) {Byte key = (Byte) key_;nodes.add(new Node02(key, map.get(key)));}return nodes;}//创建哈夫曼树public static Node02 createHuffmanTree(List<Node02> nodes) {while (nodes.size() > 1) {Collections.sort(nodes); //每次取节点前进行从小打到排序Node02 left = nodes.remove(0); //访问并移除第一元素Node02 right = nodes.remove(0); //访问并移除新的第一个元素Node02 parent = new Node02(null, left.getWeight() + right.getWeight());//创建小树parent.setLeft(left);parent.setRight(right);//将parent放入到nodes中nodes.add(parent);}return nodes.get(0); //最后nodes中的节点即为创建好的哈夫曼树}//获取赫夫曼编码 向左边路径为0  右边为1//思路//1.每个节点的赫夫曼编码保存到huffmanCodes中//2.生成赫夫曼编码的时候用到StringBuilder拼接路径static Map<Byte, String> huffmanCodes = new HashMap<>();static StringBuilder stringBuilder = new StringBuilder();/*** @param node 节点* @param code 代码编码的值 0 / 1* @param stringBuilder 用于拼接编码*/public static void getCodes(Node02 node, String code, StringBuilder stringBuilder) {StringBuilder temp = new StringBuilder(stringBuilder); //保存上次拼接的值temp.append(code); //拼接if (node != null) {if (node.getData() == null) { //node为非叶子节点getCodes(node.getLeft(), "0", temp); //向左递归遍历getCodes(node.getRight(), "1", temp); //向右递归遍历} else { //说明bide是叶子节点huffmanCodes.put(node.getData(), temp.toString()); //将相应的赫夫曼编码保存到Map中}}}//前序遍历public static void preOrder(Node02 root) {if (root != null) {root.preOrder();} else {System.out.println("树空,无法完成前序遍历!");}}}class Node02 implements Comparable<Node02> {private Byte data; //存放字符本身private int weight; //存放权值Node02 left;Node02 right;public Node02(Byte data, int weight) {this.data = data;this.weight = weight;}public Byte getData() {return data;}public void setData(Byte data) {this.data = data;}public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}public Node02 getLeft() {return left;}public void setLeft(Node02 left) {this.left = left;}public Node02 getRight() {return right;}public void setRight(Node02 right) {this.right = right;}//前序遍历public void preOrder() {System.out.println(this);if (this.getLeft() != null) {this.getLeft().preOrder();}if (this.getRight() != null) {this.getRight().preOrder();}}@Overridepublic String toString() {return "Node02{" +"data=" + data +", weight=" + weight +'}';}@Overridepublic int compareTo(Node02 o) { //从小到大排序return this.getWeight() - o.getWeight();}
}

输出结果为

总结

hungryandhumble相应字符对应的十进制与二进制如下表


若按二进制压缩 hungryandhumble的压缩代码为
011010000111010101101110011001110111001001111001011000010110111001100100011010000111010101101101011000100110110001100101 (长度为 120

若按赫夫曼编码压缩 hungryandumble的压缩代码为
01101010100000110010110110111000110101000111111101001 (长度为 52

使用赫夫曼编码压缩了 (120 - 52) / 120 = 56.7%

霍夫曼编码(huffman coding) (java实现)相关推荐

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

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

  2. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  3. 霍夫曼算法_霍夫曼编码算法

    霍夫曼算法 In this tutorial, we'll be discussing and implementing the Huffman Coding Algorithm in Java. 在 ...

  4. 算法科普:有趣的霍夫曼编码

    前言 霍夫曼编码 ( Huffman coding ) 是一种可变长的前缀码.霍夫曼编码使用的算法是 David A. Huffman 还是在MIT 的学生时提出的,并且在 1952 年发表了名为&l ...

  5. [多媒体]霍夫曼编码详解

    霍夫曼编码(Huffman Coding)_summer-CSDN博客_霍夫曼编码霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种.霍夫曼编码使用变长 ...

  6. 二进制哈夫曼编码c语言实现,二进制霍夫曼编码

    通过查看其他博客的内容,整理一篇关于二进制霍夫曼编码的笔记供大家参考和讨论,如果有错误,欢迎大家联系我批评指正. 一.二进制霍夫曼的原理 我们可以将二进制霍夫曼编码拆分理解: 二进制即 0.1: 二进 ...

  7. 霍夫曼树和霍夫曼编码以及霍夫曼编码的应用

    文章目录 霍夫曼树介绍 1.1霍夫曼树的定义 1.2霍夫曼树的几个概念 1.3构建霍夫曼树的过程 1.4代码实现霍夫曼树 霍夫曼编码介绍 什么是霍夫曼编码 通信领域的应用 字符串压缩 1.构造霍夫曼树 ...

  8. C语言Huffman Encode霍夫曼编码的算法(附完整源码)

    C语言Huffman Encode霍夫曼编码的算法 C语言Huffman Encode霍夫曼编码的算法完整源码(定义,实现,main函数测试) C语言Huffman Encode霍夫曼编码的算法完整源 ...

  9. Huffman霍夫曼树,霍夫曼编码

    霍夫曼树基本概念: 路径:从一个结点往下到孩子或孙子结点之间的同理 路径长度:如结点1到结点7的路径长度=2 结点的权:将结点的某一属性值作为结点的权 带权路径长度:从根节点到该结点*该结点的权:如结 ...

最新文章

  1. django报错:django.db.utils.OperationalError: no such table:
  2. java实现图片对比功能_Java 照片对比功能的实现
  3. 闲鱼研发框架应用和探索
  4. java 静态块初始化_简单了解java中静态初始化块的执行顺序
  5. 朗读评价语言集锦_干货 | 教师课堂评价规范用语的几点建议,建议收藏!
  6. php++背景自适应屏幕宽度,背景图片+自适应屏幕
  7. 基于ExoPlayer的ExoPlayerVideoView
  8. 百度地图、腾讯地图、高德地图经纬度转换
  9. 非常新能源铝电池项目的产业化展开的分析报告v1.1
  10. java小写金额转大写金额_java转换小写金额为大写金额
  11. Ubuntu 如何更换软件源
  12. 2.遥感传感器和遥感数据
  13. 使用Tibco项目docker部署报错异常
  14. 数据库事物,隔离级别慢慢深入
  15. 使用NuSMV解决过河问题
  16. MD-Pandoc进阶教程:图表、文献和目录
  17. Echarts y轴高度设置(宽度铺满整个父级高度)
  18. 微信小程序--保存图片到相册功能实现
  19. 自创银河系,转转转转转----Java球类的椭圆轨迹运动----立体效果
  20. python wifi密码字典

热门文章

  1. 一加支持鸿蒙吗,魅族宣布接入鸿蒙系统! Lipro 生态将携手鸿蒙
  2. C语言实现:输入一个数字判断其是否为素数
  3. ant vue table表格隐藏列
  4. 机器人genghis_机器人的发展历史你了解吗?
  5. 与初恋结婚的概率是1%
  6. 使用 WordPress Move插件网站搬家教程
  7. Chat聊天记录聊天记录导出
  8. C语言里的near和far是什么意思?
  9. file input 点击没反应_解决input file按钮要点击两次才弹出选择文件窗口
  10. iOS 当前系统的语言