当前位置:   article > 正文

JAVA——赫夫曼编码-译码器(Huffman Coding)_哈夫曼编码译码java

哈夫曼编码译码java

基本概念

哈夫曼编码(Huffman Coding):又称霍夫曼编码、赫夫曼编码-,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

源代码 

HTNode.java 

  1. package huffman;
  2. public class HTNode implements Comparable<HTNode> {
  3. int id;
  4. int weight;
  5. char code;
  6. int parent,lchild,rchild;
  7. public HTNode(int id) {
  8. this.id=id;
  9. this.weight=-1;
  10. this.code='\0';
  11. this.parent=-1;
  12. this.lchild=-1;
  13. this.rchild=-1;
  14. }
  15. public HTNode(int id,int weight) {
  16. this.id=id;
  17. this.weight=weight;
  18. this.code='\0';
  19. this.parent=-1;
  20. this.lchild=-1;
  21. this.rchild=-1;
  22. }
  23. public HTNode(int id,char code,int weight) {
  24. this.id=id;
  25. this.weight=weight;
  26. this.code=code;
  27. this.parent=-1;
  28. this.lchild=-1;
  29. this.rchild=-1;
  30. }
  31. public HTNode(int id,char code,int weight,int lchild,int rchild) {
  32. this.id=id;
  33. this.weight=weight;
  34. this.code=code;
  35. this.parent=-1;
  36. this.lchild=lchild;
  37. this.rchild=rchild;
  38. }
  39. public HTNode(int id,char code,int weight,int parent,int lchild,int rchild) {
  40. this.id=id;
  41. this.weight=weight;
  42. this.code=code;
  43. this.parent=parent;
  44. this.lchild=lchild;
  45. this.rchild=rchild;
  46. }
  47. public int compareTo(HTNode x) {
  48. if (x.weight < this.weight) {
  49. return 1;
  50. } else if (x.weight > this.weight) {
  51. return -1;
  52. }
  53. return 0;
  54. }
  55. }

HuffmanTree.java

  1. /**
  2. *
  3. */
  4. package huffman;
  5. import java.util.*;
  6. /**
  7. * @author ShenTuZhiGang
  8. * @version 1.0
  9. * @since 1.0
  10. */
  11. public class HuffmanTree {
  12. private HTNode[] HT=null;
  13. private final int MAX_INDEX=128;
  14. private char[] code;
  15. private int[] weight;
  16. private int num;
  17. private int node_tot;
  18. private String[] HuffmanCodeList;
  19. private static final char[] default_code= {' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N',
  20. 'O','P','Q','R','S','T','U','V','W','X','Y','Z'};
  21. private static final int[] default_weight= {186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};
  22. private static final int default_num=27;
  23. /**
  24. *
  25. */
  26. public HuffmanTree() {
  27. create();
  28. }
  29. /**
  30. * @param code - 字符集
  31. * @param weight - 频数
  32. */
  33. public HuffmanTree(char[] code,int[] weight) {
  34. create(code,weight);
  35. }
  36. public void create() {
  37. // TODO 自动生成的方法存根
  38. create(default_code,default_weight);
  39. }
  40. /**
  41. * @param code - 字符集
  42. * @param weight - 频数
  43. */
  44. public void create(char[] code,int[] weight) {
  45. num=code.length; //获取字符集字符总数
  46. node_tot=2*num-1; //总共需要2num-1个节点
  47. PriorityQueue<HTNode> Q = new PriorityQueue<HTNode>(); //优先队列排序
  48. HT=new HTNode[node_tot+1];
  49. HT[0]=new HTNode(0);
  50. //给叶子结点赋值
  51. for(int i=1;i<=num;i++) {
  52. HT[i]=new HTNode(i,code[i-1],weight[i-1]);
  53. Q.add(HT[i]);
  54. }
  55. int id=num;
  56. //Huffman编码
  57. while(Q.size()>=2) {
  58. //找到两个权值最小的结点作为左右子树的根节点构造新的二叉树。
  59. HTNode s1=Q.remove();
  60. HTNode s2=Q.remove();
  61. id++;
  62. //创建新的节点
  63. //新节点的权值是两个子节点之和
  64. HT[id]=new HTNode(id,'\0',s1.weight+s2.weight,s1.id,s2.id);
  65. s1.parent=s2.parent=id; //将两个子节点的父节点设置为 id;
  66. //新节点重新放入队列
  67. Q.add(HT[id]);
  68. }
  69. }
  70. /**
  71. * 从叶子到根逆向求每个字符的Huffman编码
  72. */
  73. public void createHuffmanCode() {
  74. int start,c,f;
  75. char[] cd=new char[num];
  76. HuffmanCodeList=new String[num+1]; //分配内存空间
  77. //依次对所有字符编码
  78. for(int i=1; i<=num; i++){
  79. start=num;
  80. //从叶子到根逆向求编码
  81. for(c=i,f=HT[i].parent;f!=-1;c=f,f=HT[f].parent) {
  82. if(HT[f].lchild==c) {
  83. cd[--start]='0';
  84. }else{
  85. cd[--start]='1';
  86. }
  87. }
  88. //复制编码到Huffman编码表
  89. HuffmanCodeList[i]=new String(cd,start,num-start);
  90. }
  91. }
  92. /**
  93. * @return HuffmanTreeString - HuffmanTree的字符串显示形式(括号法)
  94. */
  95. @Override
  96. public String toString() {
  97. return super.toString()+":[size="+node_tot+","+toBrackets(node_tot)+"]";
  98. }
  99. /**
  100. * @param code_str - 需要编码的字符串
  101. * @return encode - 完成Huffman编码的字符串
  102. */
  103. public String enCode(String code_str) {
  104. int len=code_str.length();
  105. String encode=new String();
  106. //依次与所有字符编码开始匹配
  107. for(int i=0;i<len;i++) {
  108. for(int j=1;j<=num;j++) {
  109. //匹配成功
  110. if(code_str.charAt(i)==HT[j].code ) {
  111. encode=encode+HuffmanCodeList[j];
  112. }
  113. }
  114. }
  115. return encode;
  116. }
  117. /**
  118. * @param code_str - 需要译码的字符串
  119. * @return encode - 完成Huffman译码的字符串
  120. */
  121. public String deCode(String code_str) {
  122. int len=code_str.length();
  123. String decode=new String();
  124. String temp=new String();
  125. //依次与所有字符编码开始匹配
  126. for(int i=0;i<len;i++) {
  127. temp=temp+code_str.charAt(i);
  128. for(int j=1;j<=num;j++) {
  129. //匹配成功
  130. if(HuffmanCodeList[j].equals(temp)) {
  131. decode=decode+HT[j].code;
  132. temp="";
  133. break;
  134. }
  135. }
  136. }
  137. return decode;
  138. }
  139. /**
  140. * 输出每个字符的Huffman编码
  141. */
  142. public void printHuffmanCodeList() {
  143. print("字符集总数:"+HT.length);
  144. for(int i=1;i<=num;i++) {
  145. print("\'"+HT[i].code+"\':"+HuffmanCodeList[i]);
  146. }
  147. }
  148. /**
  149. * 调用{@link huffman.HuffmanTree#toBrackets(int) toBrackets(int root)}方法,生成HuffmanTree的括号法表示形式
  150. * 括号法显示HuffmanTree
  151. * @return resstr - HuffmanTree的括号法表示形式
  152. */
  153. public String printHuffmanTree() {
  154. return toBrackets(node_tot);
  155. }
  156. /**
  157. * 括号法显示HuffmanTree
  158. * 递归法
  159. * @param root - HuffmanTree ROOT
  160. * @return resstr - HuffmanTree的括号法表示形式
  161. */
  162. public String toBrackets(int root) {
  163. String resstr="";
  164. if(root!=-1){
  165. resstr+=(HT[root].code=='\0')?HT[root].weight:HT[root].code;
  166. if(HT[root].lchild!=-1||HT[root].rchild!=-1){
  167. resstr+="("+toBrackets(HT[root].lchild)+","+toBrackets(HT[root].rchild)+")";
  168. }
  169. }
  170. return resstr;
  171. }
  172. public static void print(Object obj) {
  173. System.out.println(obj);
  174. }
  175. }

Main.java

  1. /**
  2. *
  3. */
  4. package huffman;
  5. /**
  6. * @author ShenTuZhiGang
  7. *
  8. */
  9. public class Main {
  10. /**
  11. * @param args
  12. */
  13. public static void main(String[] args) {
  14. // TODO 自动生成的方法存根
  15. HuffmanTree MyHT=new HuffmanTree();
  16. MyHT.createHuffmanCode();
  17. MyHT.printHuffmanCodeList();
  18. print(MyHT.enCode("THIS PROGRAME IS MY FAVORITE"));
  19. print(MyHT.deCode("1101000101100011111100001001010011000100010101011001001011111101100011111111110010100011111111110011101011000001001001001101101010"));
  20. print(MyHT.toString());
  21. print(MyHT.printHuffmanTree());
  22. }
  23. public static void print(Object obj) {
  24. System.out.println(obj);
  25. }
  26. }

运行结果

参考文章

https://blog.csdn.net/Wood_Du/article/details/80366094

https://shentuzhigang.blog.csdn.net/article/details/103198604

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/859225
推荐阅读
相关标签
  

闽ICP备14008679号