题目: 哈夫曼编码大全
描述:
关于哈夫曼树的建立,编码,解码。
输入
第一行输入数字N,代表总共有多少个字符以及权值
第二第三行分别是一行字符串,以及每个字符对应的权值
接下来输入一个数M,表示接下来有M行字符串,要求你对每个字符串进行编码
再输入一个数X,表示接下来有X行编码,要求你对每行编码进行解码
输出
第一行输出所有节点的权重
接下来输出N行,每行以 “a:001”的格式输出每个字符对应的编码
接着输出M行,对输入的字符串的编码结果
最后,输出X行的解码结果
输入样例
6
abcdef
50 10 5 5 20 10
2
abcdef
defabaabbc
2
011001100100110110101101100
1100011000110101100101100
输出样例
50 10 5 5 20 10 10 20 30 50 100
a:0
b:100
c:1100
d:1101
e:111
f:101
010011001101111101
11011111010100001001001100
accbdfadb
cacadacfb
思路:
编码:主要就是避免前面相同的部分,思路就是如果前面的找到了,但是加上后面的一个0或者1之后就找不到对应的解码字母,所以前面就是构成一个字母。
循环递归,时间可能多了点。
解码:我就是用了一个变量去标记他是1还是0,不然的话就是你要看他是在哪一边,从而判断是不是0还是1.
循环递归,时间可能还是多了点。
组成表:就是不断的选择,可以看前面的一篇博文buildHuffmanTree
相关链接:http://blog.csdn.net/zjwsa/article/details/78930200
注:时间比较长,但是这些都是最简单的理解方法。
代码如下:
package com.huffmanTree.Test; import java.util.Scanner; class Node { int spot_value;///表示左右,0还是1 int data; ///表示该点的权值 int father; ///表示该点的父亲 char ch; ///表示该点的名字字母 String p; ///表示该点的编码 /// 构造方法 public Node(int n) { spot_value = -1; data = n; father = -1; p = ""; } public Node() { spot_value = -1; data = -1; father = -1; p = ""; } } public class ManyHuffmanTree { public static Node data[]; public static int x2; public static int x1; public static int n; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); String k = sc.next(); /// 结点定义 data = new Node[n * 2]; for (int i = 1; i < n * 2; i++) data[i] = new Node(); /// 下标从1开始,方便记忆 for (int i = 1; i <= n; i++) { data[i].data = sc.nextInt(); data[i].ch = k.charAt(i - 1); } int min, max, t; for (int i = 1; i <= n - 1; i++) { /// 刚开始找两个没有父亲的作为最小最大的初始值 min = max = t = 0; for (int j = 1; j <= n + i - 1; j++) { if (data[j].father != -1) continue; if (t == 0) max = j; else min = j; t = t + 1; if (t == 2) break; } /// 先判断是不是要交换一下位置 if (data[min].data > data[max].data) { int k1 = min; min = max; max = k1; } /// 下面就是正确的寻找最小和第二小的 for (int j = 1; j <= n + i - 1; j++) { if (data[j].father != -1 || j == min || j == max) continue; if (data[j].data < data[min].data) { if (data[min].data <= data[max].data) max = min; min = j; } else if (data[max].data > data[j].data) max = j; } /// 现在就是开始赋予孩子和父亲 data[min].father = n + i; data[max].father = n + i; data[n + i].data = data[max].data + data[min].data; if (data[max].data == data[min].data) { if (max < min) { data[max].spot_value = 0; data[min].spot_value = 1; } else { data[max].spot_value = 1; data[min].spot_value = 0; } } else { if (data[max].data > data[min].data) { data[max].spot_value = 1; data[min].spot_value = 0; } else { data[max].spot_value = 0; data[min].spot_value = 1; } } } for (int i = 1; i <= n * 2 - 1; i++) System.out.print(data[i].data + " "); System.out.println(); for (int i = 1; i <= n; i++) { System.out.print(data[i].ch + ":"); search1(i, i); System.out.println(); } // 解码 int number = sc.nextInt(); for (int i = 0; i < number; i++) { String t1 = sc.next(); for (int j = 0; j < t1.length(); j++) System.out.println(data[k.indexOf(t1.charAt(j))+1].p); } /// 读码 number = sc.nextInt(); for (int i = 0; i < number; i++) { String o = sc.next(); similation(o); System.out.println(); } } private static void similation(String o) { String u = ""; for (int i = 0; i < o.length();i++) { u += o.charAt(i); if (i + 1 == o.length()) { chase(u, ""); } else { int q = i; while (true) { x1 = x2 = 0; String l = u+o.charAt(i+1); chase(u, l); if (x1 != 0 && x2 == 0) { System.out.print(data[x1].ch); u = ""; break; } q++; if(q==o.length()) break; u+=o.charAt(q); } i = q; } } } private static void chase(String u, String string) { if(string==""){ for(int k=1;k<=n;k++) { if(u.equals(data[k].p)){ System.out.print(data[k].ch); return ; } } }else{ for(int k=1;k<=n;k++) { if(x1==0 && u.equals(data[k].p)) x1 = k; if(x2==0 && string.equals(data[k].p)) x2 = k; } } } private static void search1(int index, int k) { if (data[index].father == -1) { return; } search1(data[index].father, k); data[k].p += data[index].spot_value; System.out.print(data[index].spot_value); } }