1. 程式人生 > >題目: 哈夫曼編碼大全

題目: 哈夫曼編碼大全

描述:

關於哈夫曼樹的建立,編碼,解碼。

輸入

第一行輸入數字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);
	}
}