題目: 哈夫曼編碼大全
描述:
關於哈夫曼樹的建立,編碼,解碼。
輸入
第一行輸入數字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); } }