1. //哈夫曼树类
  2. public class HaffmanTree {
  3. //最大权值
  4. static final int MAXVALUE=;
  5. int nodeNum ; //叶子结点个数
  6.  
  7. public HaffmanTree(int n)
  8. {
  9. this.nodeNum = n;
  10. }
  11.  
  12. //构造哈夫曼树算法
  13. public void haffman(int[] weight,HaffNode[] nodes)//权值数组,所有节点数组
  14. {
  15. int n = this.nodeNum;
  16. //m1,m2,表示最小的两个权值,x1,x2,表示最小两个权值对应的编号,m1表示最小,m2表示次小
  17. int m1,m2,x1,x2;
  18.  
  19. //初始化所有的结点,对应有n个叶子结点的哈夫曼树,有2n-1个结点。
  20. for(int i=;i < *n-;i++)
  21. {
  22. HaffNode temp = new HaffNode();
  23. //初始化n个叶子结点,就是输入的节点。0、1、2、3是叶子节点也是输入的节点
  24. if(i < n)
  25. {
  26. temp.weight = weight[i];
  27. }
  28. else
  29. {
  30. temp.weight = ;
  31. }
  32. temp.parent = ;
  33. temp.flag = ;
  34. temp.leftChild = -;
  35. temp.rightChild = -;
  36. nodes[i] = temp;
  37. }
  38.  
  39. for(int i=;i<n-;i++){//初始化n-1个非叶子结点,n-1表示要循环n-1次求的n-1个数。
  40. m1 = m2 = MAXVALUE;
  41. x1 = x2 =;
  42. for(int j=;j< n+i;j++)//求得这n-1个数时,每次都是从0到n+i-1,并且flag=0的,flag=1表示已经加入到二叉树。
  43. { //以下2步是找出权值最小的2个
  44. if(nodes[j].weight<m1 && nodes[j].flag==)//if成立了else、else if就不进去了。
  45. {
  46. //m1,x1初始值为第一个元素,后面如果比m1要小,则m1指向更小的,原来m1指向的现在由m2指向,
  47. //如果后面比m1大比m2小,则m2指向这个比m1大比m2小的,
  48. //也就是说m1指向最小的,m2指向第2小的。
  49. m2 = m1;
  50. x2 = x1;
  51. m1 = nodes[j].weight;
  52. x1 = j;
  53. }
  54. else if(nodes[j].weight<m2 && nodes[j].flag ==)
  55. {
  56. m2 = nodes[j].weight;
  57. x2 = j;
  58. }
  59. }
  60. //将权值最小的2个组合成一个2插树
  61. nodes[x1].parent = n+i;
  62. nodes[x2].parent = n+i;
  63. nodes[x1].flag = ;
  64. nodes[x2].flag = ;
  65. nodes[n+i].weight = nodes[x1].weight + nodes[x2].weight;
  66. nodes[n+i].leftChild = x1;
  67. nodes[n+i].rightChild = x2;
  68. }
  69. /*
  70. 初始化数组之后:[1,3,5,7,4,9,16]
  71. 编码:100、101、11、0
  72. */
  73. }
  74.  
  75. //哈弗曼编码算法
  76. public void haffmanCode(HaffNode[] nodes,Code[] haffCode)
  77. {
  78. int n = this.nodeNum;
  79. Code code = new Code(n);//
  80. int child,parent;
  81.  
  82. for(int i=;i<n; i++)//给前面n个输入的节点进行编码
  83. {
  84. code.start = n-;//
  85. code.weight = nodes[i].weight;//
  86. child = i;//
  87. parent = nodes[child].parent;
  88. //从叶子节点向上走来生成编码,画图即可。
  89. while(parent!=)
  90. {
  91. if(nodes[parent].leftChild == child)
  92. {
  93. code.bit[code.start] = ;
  94. }
  95. else
  96. {
  97. code.bit[code.start] = ;
  98. }
  99.  
  100. code.start--;
  101. child = parent;
  102. parent = nodes[child].parent;
  103. }
  104.  
  105. Code temp = new Code(n);
  106. for(int j=code.start+;j < n;j++)
  107. {
  108. temp.bit[j] = code.bit[j];
  109. }
  110. temp.weight = code.weight;
  111. temp.start = code.start;
  112. haffCode[i] = temp;
  113. }
  114. }
  115. }
  116.  
  117. //哈夫曼树的结点类
  118. public class HaffNode {
  119.  
  120. int weight; //权值
  121. int parent ;//他的双亲
  122. int flag ;//标志,是否为叶子节点
  123. int leftChild; //他的左孩子
  124. int rightChild;//他的右孩子
  125.  
  126. HaffNode()
  127. {
  128.  
  129. }
  130.  
  131. }
  132.  
  133. //哈夫曼编码类
  134. public class Code {
  135.  
  136. int[] bit; //编码的数组
  137. int start; //编码的开始下标
  138. int weight; //权值
  139. Code(int n){
  140. bit = new int[n];
  141. start = n-;
  142. }
  143. }
  144.  
  145. public class Test {
  146.  
  147. public static void main(String[] args) {
  148.  
  149. int n = ;
  150. int[] weight = {,,,};
  151. HaffmanTree haffTree = new HaffmanTree(n);
  152. HaffNode[] nodes = new HaffNode[*n-];
  153. Code[] codes = new Code[n];
  154. //构造哈夫曼树
  155. haffTree.haffman(weight, nodes);
  156. //生成哈夫曼编码
  157. haffTree.haffmanCode(nodes, codes);
  158.  
  159. //打印哈夫曼编码
  160. for(int i=;i<n;i++)
  161. {
  162. System.out.print("Weight="+codes[i].weight+" Code=");
  163. for(int j=codes[i].start+;j<n;j++)
  164. {
  165. System.out.print(codes[i].bit[j]);
  166. }
  167. System.out.println();
  168. }
  169. }
  170.  
  171. }

哈夫曼树:

带权路径长度是做小的,要使一棵二叉树的带权路径长度WPL值最小,必须使权值越大的叶结点越靠近根结点。哈夫曼提出的构造哈夫曼树构造算法为:
(1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根 结点的二叉树,从而得到一个二叉树森林F={T1,T2,…,Tn}。
(2)在二叉树森林F中选取根结点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,新的二叉树的根结点权值为左右子树根结点权值之和。
(3)在二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树加入到二叉树森林F中。
(4)重复步骤(2)和(3),当二叉树森林F中只剩下一棵二叉树时,这棵二叉树就是所构造的哈夫曼树。

哈夫曼编码问题:

哈夫曼树可用于构造代码总长度最短的编码方案。具体构造方法如下:
设需要编码的字符集合为{d1,d2,…,dn},各个字符在电文中出现的次数集合为{w1,w2,…,wn},以d1,d2,…,dn作为叶结点,以w1,w2,…,wn作为各叶结点的权值构造一棵二叉树,规定哈夫曼树中的左分支为0,右分支为1,则从根结点到每个叶结点所经过的分支对应的0和1组成的序列便为该结点对应字符的编码。这样的代码总长度最短的不等长编码称之为哈夫曼编码。

java 哈夫曼编码的更多相关文章

  1. 20172332 2017-2018-2 《程序设计与数据结构》Java哈夫曼编码实验--哈夫曼树的建立,编码与解码

    20172332 2017-2018-2 <程序设计与数据结构>Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 哈夫曼树 1.路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子 ...

  2. java实现哈夫曼编码

    java实现哈夫曼编码 哈夫曼树   既然是学习哈夫曼编码,我们首先需要知道什么是哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫 ...

  3. Java实现哈夫曼编码和解码

    最近无意中想到关于api返回值加密的问题,譬如我们的api需要返回一些比较敏感或者重要不想让截获者得到的信息,像如果是做原创图文的,文章明文返回的话则有可能被抓包者窃取. 关于请求时加密的方式比较多, ...

  4. java使用优先级队列实现哈夫曼编码

    思路: 构建小根堆 根据小根堆实现哈夫曼树 根据哈夫曼树对数据进行编码 代码实现如下: /** * @Author: DaleyZou * @Description: 使用java实现一个哈夫曼编码的 ...

  5. Java数据结构(十二)—— 霍夫曼树及霍夫曼编码

    霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...

  6. Java 树结构实际应用 二(哈夫曼树和哈夫曼编码)

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

  7. 2018.2.14 Java中的哈夫曼编码

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

  8. 10: java数据结构和算法: 构建哈夫曼树, 获取哈夫曼编码, 使用哈夫曼编码原理对文件压缩和解压

    最终结果哈夫曼树,如图所示: 直接上代码: public class HuffmanCode { public static void main(String[] args) { //获取哈夫曼树并显 ...

  9. HDU2527 哈夫曼编码

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

随机推荐

  1. enter mysql

    1, mysql -u database username -p 2, database password 3, use (database name) -> change database 4 ...

  2. Java多线程学习总结--线程同步(2)

    线程同步是为了让多个线程在共享数据时,保持数据的一致性.举个例子,有两个人同时取钱,假设用户账户余额是1000,第一个用户取钱800,在第一个用户取钱的同时,第二个用户取钱600.银行规定,用户不允许 ...

  3. SNMP 和 NetBios协议理解

      一.简单网络管理协议(SNMP,Simple Network Management Protocol)构成了互联网工程工作小组(IETF,Internet Engineering Task For ...

  4. 使用RSA非对称密钥算法实现硬件设备授权

    一.硬件设备授权 即用户在硬件设备输入一个序列号(或一个包含授权信息的文件),然后硬件设备便可正常使用.    二.授权方案 构思授权方案时,参考了下面网址的思路: http://bbs.csdn.n ...

  5. Array.prototype.slice.call

    Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组 ,::'age'}; Array.prototype.slice.call(arr); ...

  6. something: 重构、正则、vim -- clwu

    项目需要做一个db table 操作的小工具. 从phpMyAdmin上拷贝了一些代码过来修改,但我有没有足够的时间把所有拷贝过来的代码都重构修改和测试完,于是希望后面接手的同事在需要修改这些代码时能 ...

  7. 通过扩展让ASP.NET Web API支持JSONP -摘自网络

    同源策略(Same Origin Policy)的存在导致了“源”自A的脚本只能操作“同源”页面的DOM,“跨源”操作来源于B的页面将会被拒绝.同源策略以及跨域资源共享在大部分情况下针对的是Ajax请 ...

  8. HTML5边玩边学(1)画布实现方法

    一.<canvas>标签 Html5 引入了一个新的 <canvas> 标签,这个标签所代表的区域就好象一块画布,你的所有图形绘制最后都要在这块画布上呈现.有了这个标签,浏览器 ...

  9. Dagger2学习资源

    文章 Jack Wharton关于Dagger的幻灯片 代码 用Dagger2改写Jack Wharton的U+2020 我自己写的,包含了dagger2和单元测试 chiuki写的,包含了dagge ...

  10. POJ 2653 Pick-up sticks(判断线段相交)

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 7699   Accepted: 2843 De ...