哈夫曼树

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

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

ps:

节点的带权路径长度:从根节点到该节点之间的路径长度与该节点的权的乘积

带权路径长度(WPL)是设二叉树有n个叶结点,每个叶结点带有权值w,从根结点root到各个叶结点的路径长度为l,则所有叶结点带权路径长度之和为Σwl=WPL

如:

哈夫曼树的构建思路为

1.从小到大对给定的数据进行排序;

2.取出权值最小的两个数据构成二叉树,两数之和为这两个数据的父节点;

3.再将两数之和放入数据中再排序,不断重复1-2-3步骤,直到数据中,所有数据都被处理,就得到了哈夫曼树。

我们都知道,计算机本质上来说,只能储存两种东西,即数字0和1。各种文件都是编码成二进制进行存储的。


哈夫曼编码

哈夫曼编码是利用哈夫曼树的特性形成的一种编码方式,区别于定长编码,是变长编码的一种。

比如当对“i like java”这串字符若用ASCII编码的话:

那么这一串字符串如果按ACSII编码就要花费 11×8=88(bit)。每个字符都用八位的二进制来表示是很浪费的方法。当然可以用三位的二进制,只需花费 11×3=33(bit)就可以了,大小仅为ASCII编码的大小的37.5%。

在编码中,i、a都出现了两次,而剩下均只出现了一次,有没有一种编码方式让前者所花费的存储空间更少而后者可以大一些,这样在倍数的作用下使得总内存占用最少?

可以想到变长编码

但这样就有一个问题,前面字符的编码会成为后面字符编码的前缀,这样就会出现二义性,不知道表示的到底是哪一个字符,比如0表示的是“i”,那在读入11时并不是“k”,而是“ii”

哈夫曼编码就解决了这个问题,保证了编码无二义性,又使得花费的空间更小了。

任何字符的编码都不是另一字符的前缀就可以避免二义性。

用二叉树表示编码,(1)左右支分别为0、1

(2)字符只能在叶结点上。这样就保证不会有二义性。

将字符和出现的频率列出来作为树的节点和权值,用上面的思路构建哈夫曼树,然后根据路径进行编码,对节点的左右两个方向编0或1(左边编0右边编1,或者左边编1右边编0)

如上述字符串,出现频率为

则构建的哈夫曼树为

这样我们就可以找到每个字符对应唯一的哈夫曼编码。

这种编码所占空间大小为是不是少了许多呢,而且也没有发生上述开头重复的问题,当然这个例子不是很突出,出现频率更多时,会出现一位或者两位的编码。

下面就具体用代码来实现试试哈夫曼编码

通过给定字符以及相应的频率,输出对应的哈夫曼编码

字符及频率: a:6 b:7 c:1 d:2 f:2 g:1

要建哈树,就要先定义一个哈树节点

class HTreeNode{int count;//频率String  s;//代表的字符 只有叶节点才会有的int code;HTreeNode  parent;HTreeNode left;HTreeNode right;
}

先将字符数组和权值数组合并到一起--节点数组,对节点数组的每个count值进行排序,每次都是取count最低的两个节点,把这两个节点之和,再放入要排序的数组中(当然用系统的ArrayList会更方便一些,不用老是新建数组进行数据的删除和添加)

所以要经常对节点数组的count进行排序,所以要先写个排序方法

  //对数组进行排序(冒泡)private HTreeNode[]  sort(HTreeNode[] node){ for(int i=0;i<node.length;i++) {for(int j=i+1;j<node.length;j++) {if(node[i].count > node[j].count) {HTreeNode temp = new HTreeNode();temp = node[i];node[i] = node[j];node[j] = temp;}}}return node;}

   public  HTreeNode createHFMTree(int[] ca,String[] sa){ //将字符数组和权值数组合并到一起--节点数组HTreeNode[] node = new HTreeNode[sa.length];for(int i=0;i<sa.length;i++) {node[i] = new HTreeNode();node[i].s = sa[i];node[i].count =ca[i];}while(node.length>1){HTreeNode[] da=sort(node);//排序 HTreeNode n1 = da[0];HTreeNode n2 = da[1];//用这两个节点,构成一个树//把这两个节点之和,再放入要排序的数组中HTreeNode Node = new HTreeNode();Node.left = n1;Node.right = n2;n1.parent = Node;n2.parent = Node;Node.count = n1.count+n2.count;//删除n1、n2HTreeNode[] node2 = new HTreeNode[node.length-1];for(int i=2;i<node.length;i++) {node2[i-2] = node[i];}node2[node2.length-1] = Node;node = node2;}HTreeNode root = node[0];return root;//建好树的根节点;}

创建好哈夫曼树后,对节点的左右两个方向左边编0右边编1,进行前序遍历,看看字符的哈夫曼编码

 public void printTreeCode(HTreeNode root,String code){if(root != null) {if(root.left == null && root.right == null) {String m=root.s+"权值:"+root.count+" HFM编码:"+code;System.out.println(m);}printTreeCode(root.left,code+"0");printTreeCode(root.right,code+"1");}} 

看看结果

这就是哈夫曼编码的过程

java 实现部门树_(java实现)哈夫曼(Huffman)树编码(自编压缩项目基础)相关推荐

  1. 哈夫曼 (Huffman) 树的动画演示

     哈夫曼 (Huffman) 树的动画演示: http://people.cs.pitt.edu/~kirk/cs1501/animations/Huffman.html 此网站中亦有诸多其它算法 ...

  2. 数据结构入门----赫夫曼Huffman树及其应用

    最优二叉树(霍.赫.哈夫曼树) 路    径: 由一结点到另一结点间的分支所构成. 路径长度: 路径上的分支数目.a→e的路径长度=2 树的路径长度: 从树根到每一结点的路径长度之和.树长度=10 带 ...

  3. 数据结构——哈夫曼(Huffman)树+哈夫曼编码

    哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种.Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头 ...

  4. 赫夫曼(Huffman)树/编码

    一 . 基本概念: 赫夫曼树:给定带权的N个叶子构成的所有二叉树中,树的带权路径长度最小的二叉树(最优二叉树) 带权路径长度:所有树叶到树根之间的路径长度与该节点上权的乘积 权:赋予节点的有意义的参数 ...

  5. 【赫夫曼树详解】赫夫曼树简介及java代码实现-数据结构07

    赫夫曼树(最优二叉树) 1. 简介 定义: 赫夫曼树是n个带权叶子结点构成的所有二叉树中,带权路径长度(WPL)最小的二叉树. 叶子结点的带权路径: 叶子结点权值*到根节点的路径长度(叶结点的层数) ...

  6. 【数据结构】树(七)—— 哈夫曼树(C语言版)

    [数据结构]树(七)-- 哈夫曼树(C语言版) 前言 一.哈夫曼树的定义 二.哈夫曼树的构造过程描述 三.哈夫曼树的特点 四.哈夫曼树的应用--哈夫曼编码 1. 各类编码定义 2. 哈夫曼编码的构造 ...

  7. 数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)

    目录 什么是哈夫曼树 哈夫曼树的定义 哈夫曼树的构造 图解操作 代码实现 代码解析 哈夫曼树的特点 哈夫曼编码 不等长编码 二叉树用于编码 哈夫曼编码实例 什么是哈夫曼树 我们先举个例子: 要将百分制 ...

  8. 树的企业应用-哈夫曼编码树-有趣的数据压缩算法

    树的企业应用-哈夫曼编码树-有趣的数据压缩算法 哈夫曼编码 描述 张三去李四家里,但 李四是一个女生,所以张三找李四去上海迪尼斯玩 - 亚历山大.张三去伊丽莎白.李四家里,但 伊丽莎白.李四是一个女生 ...

  9. java磁盘读写b 树_原来你是这样的B+树

    前言 B+树是目前最常用的一种索引数据结构,通常用于数据库和操作系统的文件系统中,本文就网上的知识点与个人理解结合分享,如有错误,欢迎探讨及指正. 定义 B+树是B树的一种变形形式,B+树上的叶子结点 ...

最新文章

  1. Android中Gallery和ImageSwitcher的使用
  2. 这是一个测试rss的内容哦
  3. Arduino终于支持代码补全了!小白们终于可以愉快的写代码了!Arduino IDE 2.0beta功能简介...
  4. HDU - 5920 Ugly Problem(Java大数+贪心)
  5. 高品质互动在线课堂:前端开发优化实践
  6. .NET 6 Talk Party 2|.NET Core 与行业
  7. 靶场练习第十二天~vulnhub靶场之dc-4
  8. 【IE大叔的嘴歪眼斜】之—— 由hasLayout引发的临床CSS Bug表
  9. Windows 7下面安装VMware、Windows XP
  10. Ubuntu终极指南
  11. 明略数据获 10 亿人民币 C 轮融资,华兴新经济基金、腾讯领投
  12. mediacodec延时_FFmpeg优化点播延时方案
  13. java se拖动插件_JQuery之拖拽插件
  14. 自动驾驶 9-3: 走向非线性 - 扩展卡尔曼滤波器 Going Nonlinear - The Extended Kalman Filter
  15. 计算机网络图片大全,说说心情图片大全唯美
  16. 微信小程序头像为什么是模糊的?小程序头像模糊怎么办?
  17. 服务器Windows2008R2系统安全,win2008r2服务器安全设置
  18. HTML CSS游戏官网网页模板 大学生游戏介绍网站毕业设计 DW游戏主题网页模板下载 游戏娱乐网页成品代码
  19. ipv4和ipv6与int互转通用处理方式
  20. 远程服务器返回错误: (500) 内部服务器错误解决办法

热门文章

  1. python第七关再来一盘_Python爬虫自学系列(七) — 项目实战篇(一)
  2. c语言double变量后面几个0,C语言double型变量的初始化到底是是0还是0.0?
  3. json中{}和[]的区别
  4. python调用c++总结
  5. Windows 无法启动 NVIDIA Display Container LS 服务
  6. pytorch 损失函数总结
  7. '_NamespacePath' object has no attribute 'sort'
  8. 谷歌开发专家带你学AI
  9. etl常用的三种工具介绍_Adobe Photoshop常用修图插件+屏幕模式+内容感知移动工具介绍...
  10. python 视频 灰度 伽玛_Python 图像处理实战 | 图像的灰度非线性变换之对数变换、伽马变换...