实际案例——数据压缩

目标:
将给出的一段文本,比如"ilikelikelikejavadoyoulikeajava",根据前面的的赫夫曼编码原理,对其进行数据压缩处理步骤1:根据赫夫曼编码压缩数据的原理,需要创建"i like like like java do you like a java"对应的赫夫曼树.思路:前面已经分析过了,而且我们已然讲过了构建赫夫曼树的具体实现
(创建赫夫曼树->给各个字符编码->规定向左为0向右为1得到每个字符的编码)。
功能:根据赫夫曼编码压缩数据的原理,需要创建"i like like like java do you like a java"对应的赫夫曼树.思路:(1)构建一个新节点Node{data(存放数据),weight(权值),left,right}(2)得到" "对应的byte[]数组(3)编写一个方法,将构建赫夫曼树的Node节点,放在List<Node>中(形为:[Node[date=97,weight =5],Node[date=32,weight=9]]……)(4)可以通过List创建对应的赫夫曼树
我们已经生成了赫夫曼树,进行第二阶段——————  (5)生成赫夫曼编树对应的赫夫曼编码(向左记0,向右记1)形如下面
' '=01 'a'=100 'd'=11000 'u'=11001 'e'=1110 'v'=11011 'i'=101 'y'=11010 'j'=0010 'k'=1111 'l'=000 'o'=0011(6)将"i like like like java do you like a java",用上方编码编译
代码实现
package DataStructures.huffmanTree;import java.util.*;public class HuffmanCode {public static void main(String[] args) {String content = "i like like like java do you like a java";byte contentBytes[] = content.getBytes();System.out.println(contentBytes.length);//40//测试List<HuffmanNode> nodes = getHuffmanNodes(contentBytes);System.out.println("nodes" + nodes);//测试创建二叉树System.out.println("赫夫曼树");HuffmanNode HuffmanTreeRoot = creatHuffmanTree(nodes);System.out.println("前序遍历");HuffmanTreeRoot.preOreder();//测试一把是否赫夫曼编码//getCodes(HuffmanTreeRoot,"",stringBuilder);Map<Byte,String> huffmanCodes = getCodes(HuffmanTreeRoot);System.out.println("~生成的赫夫曼编码表\n"+huffmanCodes);}//生成赫夫曼树对应的赫夫曼编码里//思路//(1)将赫夫曼编码表放在Map<Byte,String>//  这个Map就跟Python的字典一样,{[key:value] [key:value]……}static Map<Byte,String> huffmanCodes = new HashMap<Byte, String>();//(2)在生成赫夫曼编码表时,需要去拼接路径,所以定义一个StringBuilder 存储某个叶子节点的路径static StringBuilder stringBuilder = new StringBuilder();//Ps:为了调用方便,我们重载一下getCodesprivate static Map<Byte,String> getCodes(HuffmanNode root){if (root==null){return null;}//处理root的左子树getCodes(root.left,"0",stringBuilder);//处理root的右子树getCodes(root.right,"1",stringBuilder);return huffmanCodes;}/*** //(3)方法* 功能:得到传入的node节点的所有赫夫曼编码,并存放到huffmanCodes集合中* @param node 传入的节点(默认从root)* @param code 该节点的路径(左节点0和右节点1)* @param stringBuilder 拼接路径*/private static void getCodes(HuffmanNode node,String code,StringBuilder stringBuilder){StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);//将传入的code加入到StringBuile2中stringBuilder2.append(code);if (node!=null){//如果node==null不处理//判断当前node时叶子节点还是非叶子节点if (node.data==null){//说明是非叶子节点//递归处理//向左getCodes(node.left,"0",stringBuilder2);//向右getCodes(node.right,"1",stringBuilder2);}else {//说明是一个叶子节点huffmanCodes.put(node.data,stringBuilder2.toString());}}}/*** @param bytes 接受的数组* @return 返回的就是List形式:[Node[date=97,weight =5],Node[date=32,weight=9]]……*/private static List<HuffmanNode> getHuffmanNodes(byte bytes[]) {//1.创建ArrayListArrayList<HuffmanNode> nodes = new ArrayList<HuffmanNode>();//2.遍历bytes,统计每个byte出现的次数->mapMap<Byte, Integer> counts = new HashMap<>();for (byte b : bytes) {Integer count = counts.get(b);if (count == null) {//Map还没有这个字符数据counts.put(b, 1);} else {counts.put(b, count + 1);}}//把每个键值对转成HuffmanNode对象,并加入nodes中//遍历Mapfor (Map.Entry<Byte, Integer> entry : counts.entrySet()) {nodes.add(new HuffmanNode(entry.getKey(), entry.getValue()));}return nodes;}//通过上面的List,常见对应的赫夫曼树private static HuffmanNode creatHuffmanTree(List<HuffmanNode> nodes) {while (nodes.size() > 1) {Collections.sort(nodes);HuffmanNode leftNode = nodes.get(0);HuffmanNode rightNode = nodes.get(1);//没有data只有权值weightHuffmanNode parent = new HuffmanNode(null, leftNode.weight + rightNode.weight);parent.left = leftNode;parent.right = rightNode;nodes.remove(leftNode);nodes.remove(rightNode);nodes.add(parent);}return nodes.get(0);}//前序遍历private static void preOreder(HuffmanNode root) {if (root != null) {root.preOreder();} else {System.out.println("空树");}}
}//创建Node
class HuffmanNode implements Comparable<HuffmanNode> {Byte data;//存放数据本身'a'->97 ' '->32int weight;//权值,字符出现的次数HuffmanNode left;HuffmanNode right;public HuffmanNode(Byte data, int weight) {this.data = data;this.weight = weight;}@Override//表示从小到达排序public int compareTo(HuffmanNode huffmanNode) {return this.weight - huffmanNode.weight;}@Overridepublic String toString() {return "HuffmanNode{" + "data=" + data + ", weight=" + weight + '}';}public void preOreder() {System.out.println(this);if (this.left != null) {this.left.preOreder();}if (this.right != null) {this.right.preOreder();}}
}
总结:1. 首先需要一个等待压缩的字符串content2. 将这个字符串放在字符数组中 contentBytes[]5+6在这里完成哦!!3. 数组建好了,就要将这个数组变成ArrayList<HuffmanNode>,得到一个动态数组(因为可以add和remove)4. 接下来我们就需要将这个动态数组中的每一个元素变成一节点,构成一颗树5. 为了完成3的变成一个节点,我们需要一个节点类class HuffmanNode6. 节点类里应该包含我们字符还有字符出现的次数,当然还有左右节点//(其实建节点5 & 6应该置前!置前!再置前!)//7. 为了完成3的构成一棵树,我们就需要专门一个静态方法private static HuffmanNode creatHuffmanTree(List<HuffmanNode> nodes)8. 方法里要有排序和建树,最后root节点也返回了,树也建好了9. 这样3确实完成了,完成了以后我们就要通过这颗树得到这棵树的赫夫曼编码了10. 我们决定将得到的赫夫曼编码存储到Map中,所以我们需要static Map<Byte,String> huffmanCodes = new HashMap<Byte, String>();11. 我们要对每一个字符进行编码,那么就需要一个方法private static void getCodes(HuffmanNode node,String code,StringBuilder stringBuilder)12. 方法里要进行递归处理,将0 和 1 放进去当从递归中出来以后将这个data对应的路径也就是编码存到Map里就可以了!13. 输出就输出huffmanCodes这个Map就可以了
//更加简洁好看的代码样子
package EXCISE;import java.util.*;public class HuffmanCodesDemo {public static void main(String[] args) {//1. 要有一个字符串String content = "In case i don't see you,good morning,good afternoon and good night";byte bytes[] = content.getBytes();//测试1,我要看看那我的句子有多长System.out.println("len=" + bytes.length);//测试2,不想看看我弄得动态数组嘛?List<aNode> list = aNodeArrayList(bytes);System.out.println("list=" + list);//测试3,我种的树不知道怎么样了。。aNode root = Planttrees(list);System.out.println("看看我的树吧!");preOreder(root);//测试4. 看看取得名字(编码)怎么样吧!GiveCodes(root, "", stringBuilder);System.out.println("这部看看我起了什么好名字么?\n" + HuffmanCodes);//测试5.完结撒花System.out.println();System.out.println(content);}//3. 动态数组list在哪呢?private static List<aNode> aNodeArrayList(byte bytes[]) {List<aNode> list = new ArrayList<aNode>();Map<Byte, Integer> counts = new HashMap<Byte, Integer>();for (byte b : bytes) {Integer count = counts.get(b);if (count == null) {counts.put(b, 1);} else {counts.put(b, count + 1);}}for (Map.Entry<Byte, Integer> entry : counts.entrySet()) {list.add(new aNode(entry.getKey(), entry.getValue()));}return list;}//4. 有list了是不是可以构建树啦?private static aNode Planttrees(List<aNode> list) {while (list.size() > 1) {Collections.sort(list);aNode leftNode = list.get(0);aNode rightNode = list.get(1);aNode parent = new aNode(null, leftNode.weight + rightNode.weight);parent.left = leftNode;parent.right = rightNode;list.remove(leftNode);list.remove(rightNode);list.add(parent);}return list.get(0);}//4.1树出来了我们遍历一下看看成果吧private static void preOreder(aNode root) {if (root != null) {root.preorder();} else {System.out.println("空");}}//5. 起名字要做准备呀!// 首先是Map<Byte,String> HuffmanCodes帮我存一下所有果实的名字// 然后是StringBuilder stringBuilder帮我拼接一下想好的序号哦!static Map<Byte, String> HuffmanCodes = new HashMap<Byte, String>();static StringBuilder stringBuilder = new StringBuilder();//6. 准备结束啦!其名字吧,一口气起完好了!就用递归!private static void GiveCodes(aNode node, String Code, StringBuilder stringBuilder) {StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);stringBuilder1.append(Code);if (node != null) {if (node.aByte == null) {GiveCodes(node.left, "0", stringBuilder1);GiveCodes(node.right, "1", stringBuilder1);} else {HuffmanCodes.put(node.aByte, stringBuilder.toString());}}}
}//2. Node在哪呢?
class aNode implements Comparable<aNode> {Byte aByte;int weight;aNode left;aNode right;public aNode(Byte aByte, int weight) {this.aByte = aByte;this.weight = weight;}@Overridepublic int compareTo(aNode aNode) {return this.weight - aNode.weight;}@Overridepublic String toString() {return "HuffmanNode{" + "aByte=" + aByte + ", weight=" + weight + '}';}public void preorder() {System.out.println(this);if (this.left != null) {this.left.preorder();}if (this.right != null) {this.right.preorder();}}
}

韩顺平 数据结构与算法 (12_4) 赫夫曼编码(代码)相关推荐

  1. 尚硅谷Java数据结构和java算法,韩顺平数据结构和算法课后作业01

    尚硅谷Java数据结构和java算法,韩顺平数据结构和算法课后作业第一题 要求: 1)在前面的基础上,将稀疏数组保存到磁盘上,比如map.data 2) 恢复原来的数组时,读取map.data进行恢复 ...

  2. 韩顺平 数据结构与算法 (12_6) 树结构应用部分_赫夫曼编码实践——数据解码

    赫夫曼编码实践--数据解码 代码实现(承袭压缩的代码) package DataStructures.huffmanTree;import javax.print.DocFlavor; import ...

  3. 韩顺平 数据结构与算法 (12_3) 树结构应用部分_赫夫曼编码(思路)

    赫夫曼编码(思路) 1.基本介绍 赫夫曼编码也翻译为哈夫曼编码(Huffman Coding),又称赫夫曼编码, 赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一 赫夫曼编码广泛的用于数据文件压缩与 ...

  4. 韩顺平 数据结构与算法 (11_1) 树结构基础部分_二叉树

    3)二叉树 1. 二叉树的概念 树有很多种,每个节点最多只有两个子节点的形式就是二叉树 二叉树的子节点分为左节点和右节点 如果该二叉树的所有叶子节点都在最后一层并且结点总数=2^n-1(n为层数)我们 ...

  5. 堆排序算法回顾---(韩顺平数据结构)笔记

    堆排序 是利用堆这种数据结构而设计的一种排序算法,它是一种选择排序, 时间复杂度和空间复杂度 最坏和最好的平均时间复杂度均为 O(nlogn) 它是不稳定的排序,空间复杂度O(1) 堆的定义 大顶堆: ...

  6. 克鲁斯卡尔算法---(韩顺平数据结构)笔记

    克鲁斯卡尔算法 本质:从某一顶点为起点,逐步找各个顶点最小权值的边来构成最小生成树.那我们也可以直接从边出发,寻找权值最小的边来构建最小生成树.不过在构建的过程中要考虑是否会构成回环的情况 用来求加权 ...

  7. 韩老师——数据结构与算法—单链表的生成及增删改查操作和常见关于链表的面试题java代码实现

    话不多说直接上代码. public class SingleLinkedListDemo {public static void main(String[] args) {//测试HeroNode n ...

  8. 普利姆算法(prim)---(韩顺平数据结构)笔记

    普利姆算法 本质:求出从某一结点开始到达其他结点距离花费最少的组合 从图中指定顶点出发,寻找它相连的所有结点,比较这些结点的权值大小,然后连接权值最小的那个结点. 然后将寻找这两个结点相连的所有结点, ...

  9. 数据结构与算法课程的代码链接

    VS2005版本 http://download.csdn.net/detail/lsgo_myp/9713329 VS2015版本 http://download.csdn.net/detail/l ...

最新文章

  1. LIO-SAM: 紧耦合的激光与惯导里程计方案
  2. 人类未来将毁于元宇宙?刘慈欣向往星辰大海,小扎却要深耕Meta
  3. libsvm 训练后,模型参数详解
  4. 35.6. /etc/dnsmasq.d/dnsmasq.address.conf
  5. java socket 浏览器_java实现websocket(图文)
  6. 谷歌绝不会退出中国市场
  7. 小程序游戏开发一般多少钱?游戏小程序开发制作
  8. pm2开启nuxt项目pm2 start ./node_modules/nuxt/bin/nuxt-start
  9. Android圆角ImageView的几种实现方式(包含四个角的分别设置)
  10. Oracle树形结构拖拽之插队重新排序
  11. 邮箱密码忘了怎么找回
  12. 5.5 设置UITableView单元格背景色 [原创iOS开发-Xcode教程]
  13. 1亿条数据批量插入 MySQL,哪种方式最快
  14. FMC150-两路250Msps AD、两路500Msps DA FMC子卡模块
  15. Springboot框架整合Mybatis-plus实战动态SQL以及常见的Mybatis面试题
  16. 不同颜色的RGB值、透明度A
  17. 又出事了?网站被攻击了?高中生?
  18. 分享保护视力应用桌面
  19. 周易六十四卦——解卦
  20. 本页面是由KSWEB生成的web包

热门文章

  1. 李笑来老师的财务自由之路读书笔记
  2. 联合体的特点及其大小的计算
  3. Blender猫咪的头部骨骼绑定【Auto Rig Pro自我摸索0.1版本】
  4. 手机C语言编程软件c4droid试用
  5. 面向对象五大设计原则-里氏代换原则
  6. 第4章 C程序结构语句
  7. 爬取当当网 Top 500 本五星好评书籍
  8. 独特的建模软件-----Fusion360
  9. LiveGBS国标GB/T28181国标视频流媒体平台如何对接海康大华宇视等监控摄像头报警消息报警订阅国标报警信息
  10. TTL与CMOS电平