哈夫曼编码实现

x33g5p2x  于2022-06-20 转载在 其他  
字(3.1k)|赞(0)|评价(0)|浏览(481)

一 点睛

在构造哈夫曼树的过程中,首先将每个节点的双亲、左孩子、右孩子都初始化为-1,找出所有节点中双亲为 -1 且权值最小的两个节点 t1 和 t2,并合并为一棵二叉树,更新信息(双亲节点的权值为 t1、t2 权值之和,其左孩子为权值最小的节点 t1,右孩子为次小的节点 t2,t1、t2 的双亲为双亲节点的编号)。重复此过程,建成一棵哈夫曼树。

二 数据结构

每个节点的结构都包括权值、双亲、左孩子、右孩子、节点字符信息五个域。如下图所示:

| <br>weight<br> | <br>parent<br> | <br>lchild<br> | <br>rchild<br> | <br>value<br> |

在结构体的编码过程中,bit[] 存放节点的编码,start 记录编码开始时的下标,在逆向编码存储时,start 从 n-1 开始依次递减,从后向前存储,当读取时,从start+1 开始到 n-1,从前向后输出,即该字符的编码。

三 算法实现

  1. package tree;
  2. import java.util.Scanner;
  3. public class Huffman {
  4. static int MAXBIT = 100;
  5. static int MAXVALUE = 10000;
  6. static int MAXLEAF = 30;
  7. static int MAXNODE = MAXLEAF * 2 - 1;
  8. /* 构造哈夫曼树 */
  9. static void HuffmanTree(HNodeType HuffNode[], int n) {
  10. /*
  11. i、j: 循环变量,
  12. m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
  13. x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/
  14. int i, j, x1, x2;
  15. double m1, m2;
  16. Scanner scanner = new Scanner(System.in);
  17. /* 初始化存放哈夫曼树数组 HuffNode[] 中的结点 */
  18. for (i = 0; i < 2 * n - 1; i++) {
  19. HuffNode[i].weight = 0; // 权值
  20. HuffNode[i].parent = -1;
  21. HuffNode[i].lchild = -1;
  22. HuffNode[i].rchild = -1;
  23. }
  24. /* 输入 n 个叶子结点的权值 */
  25. for (i = 0; i < n; i++) {
  26. System.out.println("请输入节点字符和节点权值:");
  27. HuffNode[i].value = scanner.next().charAt(0);
  28. HuffNode[i].weight = scanner.nextInt();
  29. }
  30. /* 构造 Huffman 树 */
  31. for (i = 0; i < n - 1; i++) { // 执行 n-1 次合并
  32. /* m1、m2 中存放两个无父结点且结点权值最小的两个结点 */
  33. m1 = m2 = MAXVALUE;
  34. x1 = x2 = 0;
  35. /* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一棵二叉树 */
  36. for (j = 0; j < n + i; j++) {
  37. if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1) {
  38. m2 = m1;
  39. x2 = x1;
  40. m1 = HuffNode[j].weight;
  41. x1 = j;
  42. } else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1) {
  43. m2 = HuffNode[j].weight;
  44. x2 = j;
  45. }
  46. }
  47. /* 设置找到的两个子结点 x1、x2 的父结点信息 */
  48. HuffNode[x1].parent = n + i;
  49. HuffNode[x2].parent = n + i;
  50. HuffNode[n + i].weight = m1 + m2;
  51. HuffNode[n + i].lchild = x1;
  52. HuffNode[n + i].rchild = x2;
  53. //System.out.println("本轮中X1的权值:" + HuffNode[x1].weight + "\t本轮中X1的权值:" + HuffNode[x2].weight); // 用于测试
  54. }
  55. }
  56. /* 哈夫曼树编码 */
  57. static void HuffmanCode(HCodeType HuffCode[], HNodeType HuffNode[], int n) {
  58. HCodeType cd = new HCodeType(); /* 定义一个临时变量来存放求解编码时的信息 */
  59. int i, j, c, p;
  60. for (i = 0; i < n; i++) {
  61. cd.start = n - 1;
  62. c = i;
  63. p = HuffNode[c].parent;
  64. while (p != -1) {
  65. if (HuffNode[p].lchild == c)
  66. cd.bit[cd.start] = 0;
  67. else
  68. cd.bit[cd.start] = 1;
  69. cd.start--; /*前移一位 */
  70. c = p;
  71. p = HuffNode[c].parent; /* 设置下一循环条件 */
  72. }
  73. /* 把叶子结点的编码信息从临时编码 cd 中复制出来,放入编码结构体数组 */
  74. for (j = cd.start + 1; j < n; j++)
  75. HuffCode[i].bit[j] = cd.bit[j];
  76. HuffCode[i].start = cd.start;
  77. }
  78. }
  79. public static void main(String[] args) {
  80. int i, j, n;
  81. System.out.println("请输入n:");
  82. Scanner scanner = new Scanner(System.in);
  83. n = scanner.nextInt();
  84. /* 定义一个结点结构体数组 */
  85. HNodeType HuffNode[] = new HNodeType[MAXNODE];
  86. /* 定义一个编码结构体数组*/
  87. HCodeType HuffCode[] = new HCodeType[MAXLEAF];
  88. for (int i1 = 0; i1 < HuffNode.length; i1++) {
  89. HuffNode[i1] = new HNodeType();
  90. }
  91. for (int i1 = 0; i1 < HuffCode.length; i1++) {
  92. HuffCode[i1] = new HCodeType();
  93. }
  94. HuffmanTree(HuffNode, n); //构造哈夫曼树
  95. HuffmanCode(HuffCode, HuffNode, n); // 哈夫曼树编码
  96. // 输出已保存好的所有存在编码的哈夫曼编码
  97. for (i = 0; i < n; i++) {
  98. System.out.println(HuffNode[i].value + "哈夫曼编码是:");
  99. for (j = HuffCode[i].start + 1; j < n; j++) {
  100. System.out.printf(" " + HuffCode[i].bit[j]);
  101. }
  102. System.out.println();
  103. }
  104. }
  105. }
  106. // 节点的数据结构
  107. class HNodeType {
  108. public double weight;
  109. public int parent;
  110. public int lchild;
  111. public int rchild;
  112. public char value;
  113. }
  114. // 每个节点的编码
  115. class HCodeType {
  116. public int bit[] = new int[Huffman.MAXBIT];
  117. public int start;
  118. }

四 测试结果

绿色为输入,白色为输出。

相关文章