- 哈夫曼(Huffman)树创建及其带权路径长度(WPL)、哈夫曼编码、哈夫曼解码
package ccnu.offer.tree;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
public class Demo06 {public static void test1(){List<HuffmanNode> nodes = new ArrayList<HuffmanNode>();nodes.add(new HuffmanNode("A", 40.0));nodes.add(new HuffmanNode("B", 8.0));nodes.add(new HuffmanNode("C", 10.0));nodes.add(new HuffmanNode("D", 30.0));nodes.add(new HuffmanNode("E", 10.0));nodes.add(new HuffmanNode("F", 2.0));HuffmanNode root = createHuffmanTree(nodes);inOrder(root);System.out.println();System.out.println("WPL=" + getTreeWPL(root));System.out.println(getLeavesPL(root, 0));HashMap<String, String> h = getCharactersHuffmanEncoding(root);Set<Entry<String, String>> entrys = h.entrySet();for(Entry<String, String> entry : entrys){System.out.println(entry.getKey() + ": " + entry.getValue());}System.out.println(textToNodesList("C:\\Users\\" + System.getenv("username") + "\\Desktop\\huffmanIn.txt"));}public static void test2(){String src = "C:\\Users\\" + System.getenv("username") + "\\Desktop\\huffmanIn.txt"; String dest = "C:\\Users\\" + System.getenv("username") + "\\Desktop\\huffmanOut.txt"; String dest2 = "C:\\Users\\" + System.getenv("username") + "\\Desktop\\copyOfHuffmanIn.txt"; HuffmanNode root = createHuffmanTree(textToNodesList(src));System.out.println("WPL=" + getTreeWPL(root));getTextHuffmanEncoding(src, dest);getTextHuffmanDecoding(getCharactersHuffmanEncoding(root), dest, dest2);}public static void main(String[] args) {test1();test2();String src = "C:\\Users\\" + System.getenv("username") + "\\Desktop\\huffmanIn.txt"; System.out.println(textToNodesList(src));}public static HuffmanNode createHuffmanTree(List<HuffmanNode> f) { if (f == null) {return null;}if (f.size() == 0) { return null; }while (f.size() > 1) {f.sort(null); HuffmanNode l = f.get(0);HuffmanNode r = f.get(1);HuffmanNode newNode = new HuffmanNode(l.data + r.data, l.weight + r.weight, l, r); f.remove(0);f.remove(0);f.add(newNode);}return f.get(0); }public static HashMap<String, String> getCharactersHuffmanEncoding(HuffmanNode root){return getCharactersHuffmanEncoding(root, "");}private static HashMap<String, String> getCharactersHuffmanEncoding(HuffmanNode root, String encoding){Map<String, String> characterEncodingResultSet = new HashMap<String, String>();if(root == null){return null;}if(root.lchild == null && root.rchild == null){ characterEncodingResultSet.put(root.data, encoding);}else{ characterEncodingResultSet.putAll(getCharactersHuffmanEncoding(root.lchild, encoding + "0")); characterEncodingResultSet.putAll(getCharactersHuffmanEncoding(root.rchild, encoding + "1")); }return (HashMap<String, String>)characterEncodingResultSet;}public static ArrayList<HuffmanNode> textToNodesList(String pathname) {if (pathname == null || pathname.length() == 0) {return null;}ArrayList<HuffmanNode> huffmanNodes = new ArrayList<HuffmanNode>();HashMap<String, Double> dwMap = new HashMap<String, Double>(); BufferedReader br = null;try {br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(pathname))));char ch;while (true) {int i = br.read(); if (i == -1) { break;} else {ch = (char) i;}double count = 1;if (dwMap.containsKey(String.valueOf(ch))) {count = dwMap.get(String.valueOf(ch)) + 1; }dwMap.put(String.valueOf(ch), count);}br.close();} catch (FileNotFoundException e1) {e1.printStackTrace();} catch (IOException e) {e.printStackTrace();}Set<Entry<String, Double>> entrys = dwMap.entrySet();for (Entry<String, Double> entry : entrys) { huffmanNodes.add(new HuffmanNode(entry.getKey(), entry.getValue()));}return huffmanNodes;}public static void getTextHuffmanEncoding(String textSrc, String textDest) {if (textSrc == null || textDest == null) {return;}ArrayList<HuffmanNode> huffmanNodes = textToNodesList(textSrc); HuffmanNode root = createHuffmanTree(huffmanNodes); HashMap<String, String> characterEncodingResultSet = getCharactersHuffmanEncoding(root); BufferedReader br = null;BufferedWriter bw = null;try {br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(textSrc))));bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(textDest))));char ch;while (true) {int i = br.read();if (i == -1) {break;} else {ch = (char) i;}String characterEncoding = characterEncodingResultSet.get(String.valueOf(ch)); bw.write(characterEncoding);}bw.flush();bw.close();br.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public static void getTextHuffmanDecoding(Map<String, String> decoder, String textSrc, String textDest){if(textSrc == null || textDest == null){return;}BufferedReader br = null;BufferedWriter bw = null;String tmp = "";try {br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(textSrc))));bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(textDest))));while(true){int i = br.read();if(-1 == i){break;}else{tmp += (char)i;}if(decoder.containsValue(tmp)){String data = getKeysByValue(decoder, tmp)[0]; if(data.equals("")){ bw.write("\n\r");}else{bw.write(data);}tmp = ""; }}bw.flush();bw.close();br.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public static String[] getKeysByValue(Map map, String value) {StringBuffer sb = new StringBuffer();Set<Entry<String, String>> entrys = map.entrySet();Iterator<Map.Entry<String, String>> iter = entrys.iterator();while(iter.hasNext()){Map.Entry<String, String> entry = iter.next();String value2 = entry.getValue();if(value2 != null && value2.equals(value)){ sb.append(entry.getKey() + " ");}}String keys = sb.toString().trim();return keys.split(" +");}public static void inOrder(HuffmanNode root){if(root != null){inOrder(root.lchild);if(root.lchild == null && root.rchild == null){ System.out.print(root.data + " ");}inOrder(root.rchild);}}public static double getTreeWPL(HuffmanNode root){ Stack<HuffmanNode> nodes = new Stack<HuffmanNode>();double WPL = 0;while(root != null || !nodes.isEmpty()){if(root != null){nodes.push(root);root = root.lchild;}else{root = nodes.peek(); if(root.tag){ nodes.pop(); root = null; }else{ root.tag = true;if(root.lchild == null && root.rchild == null){WPL += (nodes.size() - 1) * root.weight;}root = root.rchild;}}}return WPL;}public static ArrayList<Integer> getLeavesPL(HuffmanNode root, int depth) {ArrayList<Integer> pls = new ArrayList<Integer>();if (root == null) {return null;}if (root.lchild == null && root.rchild == null) {pls.add(depth);return pls;} else {pls.addAll(getLeavesPL(root.lchild, depth + 1));pls.addAll(getLeavesPL(root.rchild, depth + 1));}return pls;}private static class HuffmanNode implements Comparable<HuffmanNode> {private String data; private double weight; private HuffmanNode lchild;private HuffmanNode rchild;private boolean tag; public HuffmanNode(String data, double weight) {this(data, weight, null, null);}public HuffmanNode(String data, double weight, HuffmanNode lchild, HuffmanNode rchild){this.data = data;this.weight = weight;this.lchild = lchild;this.rchild = rchild;}@Overridepublic int compareTo(HuffmanNode o) {if (o == null) {return 0;}if (this.weight > o.weight) {return 1;} else if (this.weight == o.weight) {return 0;} else {return -1;}}@Overridepublic String toString() {return data + "=" + weight;}}
}