/** * @Author: HuWan Peng * @Date Created in 23:21 2018/1/14 */ public class Node { char data; // 數據 int weight; // 權值 int left, right, parent; // 三條連接 public Node (char data, int weight) { this.data = data; this.weight = weight; } public Node (int weight) { this.weight = weight; } }
具體代碼java
/** * @description: 構建赫夫曼樹 */ public Node[] buildTree (Node [] nodes) { int s1, s2,p; int n = nodes.length; // 外結點的數量 int m = 2*n - 1; // 內結點 + 外結點的總數量 Node [] HT = new Node [m]; // 存儲結點對象的HT數組 for (int i=0;i<m;i++) HT[i] = new Node(0); // 初始化HT數組元素 for (int i=0;i<n;i++) { HT[i].data = nodes[i].data; HT[i].weight = nodes[i].weight; //將給定的權值列表賦給外結點對象 } for (int i=n;i<m;i++) { s1 = select(HT,i,0); // 取得HT數組中權值最小的結點對象的下標 s2 = select(HT,i,1); // 取得HT數組中權值次小的結點對象的下標 HT[i].left = s1; // 創建連接 HT[i].right = s2; HT[s1].parent = i; HT[s2].parent = i; HT[i].weight = HT[s1].weight + HT[s2].weight;// 計算當前外結點的權值 selectStart+=2; // 這個變量表示以前「被刪除」的最小結點的數量和 } return HT; // 將處理後的HT數組返回 }
/** * @description: buildTree方法的用例 */ public static void main (String [] args) { Node [] nodes = new Node[4]; nodes[0] = new Node('a',7); nodes[1] = new Node('b',5); nodes[2] = new Node('c',2); nodes[3] = new Node('d',4); HuffmanTree ht = new HuffmanTree(); Node [] n = ht.buildTree(nodes); // n是構建完畢的赫夫曼樹 } }
private int select (Node[] HT,int range, int rank)
s1 = select(HT,i,0); // 取得HT數組中權值最小的結點對象的下標 s2 = select(HT,i,1); // 取得HT數組中權值次小的結點對象的下標
/** * @description: 返回權值排名爲rank的結點對象在HT中的下標(按權值從小到大排) */ private int select (Node[] HT,int range, int rank) { Node [] copyNodes = Arrays.copyOf(HT, range);// 將HT[0]~HT[range]拷貝到copyNodes中 QuickSort.sort(copyNodes); // 對copyNodes進行從小到大的快速排序 Node target = copyNodes[rank + selectStart]; // 取得「刪除」後權值排名爲rank的結點對象 for (int j=0;j<HT.length;j++) { if (target == HT[j]) return j; // 返回該結點對象在數組HT中的下標 } return -1; }
import java.util.Arrays; /** * @Author: HuWan Peng * @Date Created in 22:54 2018/1/14 */ public class HuffmanTree { private class HuffmanCode { char data; // 存放字符,例如 'C' String bit; // 存放編碼後的字符串, 例如"111" public HuffmanCode (char data, String bit) { this.data = data; this.bit = bit; } } /** * @description: 構建赫夫曼樹 */ public Node[] buildTree (Node [] nodes) { // 具體代碼見上文 } /** * @description: 進行赫夫曼編碼 */ public HuffmanCode [] encode(Node [] nodes) { Node [] HT = buildTree(nodes); // 根據輸入的nodes數組構造赫夫曼樹 int n = nodes.length; HuffmanCode [] HC = new HuffmanCode [n]; String bit; for (int i=0;i<n;i++) { // 遍歷各個葉子結點 bit = ""; for (int c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) { // 從葉子結點上溯到根結點 if(HT[f].left == c) bit= "0" + bit; // 反向編碼 else bit= "1" + bit; } HC[i] = new HuffmanCode(HT[i].data,bit); // 將字符和對應的編碼存儲起來 } return HC; } /** * @description: encode方法的用例 */ public static void main (String [] args) { Node [] nodes = new Node[4]; nodes[0] = new Node('A',7); nodes[1] = new Node('B',5); nodes[2] = new Node('C',2); nodes[3] = new Node('D',4); HuffmanTree ht = new HuffmanTree(); HuffmanCode[] hc = ht.encode(nodes); // 對A,B,C,D進行編碼 for (int i=0;i<hc.length;i++) { // 將赫夫曼編碼打印出來 System.out.println(hc[i].data + ":" +hc[i].bit); } } }
A:0 B:10 C:110 D:111
import java.util.Arrays;
/** * @Author: HuWan Peng * @Date Created in 22:54 2018/1/14 */ public class HuffmanTree { int selectStart = 0; private class HuffmanCode { char data; // 存放字符,例如 'C' String bit; // 存放編碼後的字符串, 例如"111" public HuffmanCode (char data, String bit) { this.data = data; this.bit = bit; } } /** * @description: 構建赫夫曼樹 */ public Node[] buildTree (Node [] nodes) { // 代碼見上文 } /** * @description: 進行赫夫曼譯碼 */ public String decode (Node [] nodes, String code) { String str=""; Node [] HT = buildTree(nodes); int n =HT.length -1; for (int i=0;i<code.length();i++) { char c = code.charAt(i); if(c == '1') { n = HT[n].right; } else { n = HT[n].left; } if(HT[n].left == 0) { str+= HT[n].data; n =HT.length -1; } } return str; } /** * @description: decode方法的用例 */ public static void main (String [] args) { Node [] nodes = new Node[4]; nodes[0] = new Node('A',7); nodes[1] = new Node('B',5); nodes[2] = new Node('C',2); nodes[3] = new Node('D',4); HuffmanTree ht = new HuffmanTree(); // 對 010110111 進行譯碼 System.out.println(ht.decode(nodes,"010110111")); } }
ABCD
/** * @Author: HuWan Peng * @Date Created in 23:21 2018/1/14 */ public class Node { char data; int weight; int left, right, parent; public Node (char data, int weight) { this.data = data; this.weight = weight; } public Node (int weight) { this.weight = weight; } }
import java.util.Arrays; /** * @Author: HuWan Peng * @Date Created in 22:54 2018/1/14 */ public class HuffmanTree { int selectStart = 0; private class HuffmanCode { char data; // 存放字符,例如 'C' String bit; // 存放編碼後的字符串, 例如"111" public HuffmanCode (char data, String bit) { this.data = data; this.bit = bit; } } /** * @description: 返回權值排名爲rank的結點對象在nodes中的下標(按權值從小到大排) */ private int select (Node[] HT,int range, int rank) { Node [] copyNodes = Arrays.copyOf(HT, range);// 將HT[0]~HT[range]拷貝到copyNodes中 QuickSort.sort(copyNodes); // 對copyNodes進行從小到大的快速排序 Node target = copyNodes[rank + selectStart]; // 取得「刪除」後權值排名爲rank的結點對象 for (int j=0;j<HT.length;j++) { if (target == HT[j]) return j; // 返回該結點對象在數組HT中的下標 } return -1; } /** * @description: 構建赫夫曼樹 */ public Node[] buildTree (Node [] nodes) { int s1, s2,p; int n = nodes.length; // 外結點的數量 int m = 2*n - 1; // 內結點 + 外結點的總數量 Node [] HT = new Node [m]; // 存儲結點對象的HT數組 for (int i=0;i<m;i++) HT[i] = new Node(0); // 初始化HT數組元素 for (int i=0;i<n;i++) { HT[i].data = nodes[i].data; HT[i].weight = nodes[i].weight; //將給定的權值列表賦給外結點對象 } for (int i=n;i<m;i++) { s1 = select(HT,i,0); // 取得HT數組中權值最小的結點對象的下標 s2 = select(HT,i,1); // 取得HT數組中權值次小的結點對象的下標 HT[i].left = s1; // 創建連接 HT[i].right = s2; HT[s1].parent = i; HT[s2].parent = i; HT[i].weight = HT[s1].weight + HT[s2].weight;// 計算當前外結點的權值 selectStart+=2; // 這個變量表示以前「被刪除」的最小結點的數量和 } return HT; // 將處理後的HT數組返回 } /** * @description: 進行赫夫曼編碼 */ public HuffmanCode [] encode(Node [] nodes) { Node [] HT = buildTree(nodes); // 根據輸入的nodes數組構造赫夫曼樹 int n = nodes.length; HuffmanCode [] HC = new HuffmanCode [n]; String bit; for (int i=0;i<n;i++) { // 遍歷各個葉子結點 bit = ""; for (int c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) { // 從葉子結點上溯到根結點 if(HT[f].left == c) bit= "0" + bit; // 反向編碼 else bit= "1" + bit; } HC[i] = new HuffmanCode(HT[i].data,bit); // 將字符和對應的編碼存儲起來 } return HC; } /** * @description: 進行赫夫曼譯碼 */ public String decode (Node [] nodes, String code) { String str=""; Node [] HT = buildTree(nodes); int n =HT.length -1; for (int i=0;i<code.length();i++) { char c = code.charAt(i); if(c == '1') { n = HT[n].right; } else { n = HT[n].left; } if(HT[n].left == 0) { str+= HT[n].data; n =HT.length -1; } } return str; } /** * @description: buildTree方法的用例 */ public static void main (String [] args) { Node [] nodes = new Node[4]; nodes[0] = new Node('A',7); nodes[1] = new Node('B',5); nodes[2] = new Node('C',2); nodes[3] = new Node('D',4); HuffmanTree ht = new HuffmanTree(); System.out.println(ht.decode(nodes,"010110111")); } }
/** * @Author: HuWan Peng * @Date Created in 22:56 2018/1/14 */ public class QuickSort { /** * @description: 交換兩個數組元素 */ private static void exchange(Node [] a , int i, int j) { Node temp = a[i]; a[i] = a[j]; a[j] = temp; } /** * @description: 切分函數 */ private static int partition (Node [] a, int low, int high) { int i = low, j = high+1; // i, j爲左右掃描指針 int pivotkey = a[low].weight; // pivotkey 爲選取的基準元素(頭元素) while(true) { while (a[--j].weight>pivotkey) { if(j == low) break; } // 右遊標左移 while(a[++i].weight<pivotkey) { if(i == high) break; } // 左遊標右移 if(i>=j) break; // 左右遊標相遇時候中止, 因此跳出外部while循環 else exchange(a,i, j) ; // 左右遊標未相遇時中止, 交換各自所指元素,循環繼續 } exchange(a, low, j); // 基準元素和遊標相遇時所指元素交換,爲最後一次交換 return j; // 一趟排序完成, 返回基準元素位置 } /** * @description: 根據給定的權值對數組進行排序 */ private static void sort (Node [] a, int low, int high) { if(high<= low) { return; } // 當high == low, 此時已經是單元素子數組,天然有序, 故終止遞歸 int j = partition(a, low, high); // 調用partition進行切分 sort(a, low, j-1); // 對上一輪排序(切分)時,基準元素左邊的子數組進行遞歸 sort(a, j+1, high); // 對上一輪排序(切分)時,基準元素右邊的子數組進行遞歸 } public static void sort (Node [] a){ //sort函數重載, 只向外暴露一個數組參數 sort(a, 0, a.length-1); } }