题目: 哈夫曼编码大全
描述:
关于哈夫曼树的建立,编码,解码。
输入
第一行输入数字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);
}
}

浙公网安备 33010602011771号