實現時參考了博客
java建立哈夫曼樹和實現哈夫曼編碼和坤澎的博客——java實現哈夫曼編碼,在讀懂代碼的同時,在一些地方加上了本身的備註html
HuffmanNode
利用泛型實現結點,定義左子樹,右子樹,權值和編碼。// 哈夫曼節點類 public class HuffmanNode<T> implements Comparable<HuffmanNode<T>> { private T data; // 數據 private double weight; // 權重 private HuffmanNode<T> left; private HuffmanNode<T> right; String code; // 編碼 public HuffmanNode(T data, double weight){ this.data = data; this.weight = weight; this.code = ""; } public T getData() { return data; } public void setData(T data) { this.data = data; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } public HuffmanNode<T> getLeft() { return left; } public void setLeft(HuffmanNode<T> left) { this.left = left; } public HuffmanNode<T> getRight() { return right; } public void setRight(HuffmanNode<T> right) { this.right = right; } public String getCode(){ return code; } public void setCode(String str){ code = str; } @Override public String toString(){ return null; } @Override public int compareTo(HuffmanNode<T> other) { if(other.getWeight() > this.getWeight()){ return 1; } if(other.getWeight() < this.getWeight()){ return -1; } return 0; } }
ReadTxt
類讀取txt文件中的字母,用於將字母轉化成哈夫曼編碼。// 讀取文件類 public class ReadTxt { char[] chars = new char[]{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s' ,'t','u','v','w','x','y','z',' '}; // int[] nu = new int[26]; int[] number = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; public String txtString(File file){ StringBuilder result = new StringBuilder(); try{ BufferedReader br = new BufferedReader(new FileReader(file));//構造一個BufferedReader類來讀取文件 String s = null; while((s = br.readLine())!=null){// 使用readLine方法,一次讀一行 result.append(System.lineSeparator() + s); num(s); } br.close(); }catch(Exception e){ e.printStackTrace(); } return result.toString(); } public void num(String string){ // 26個字母加一個空格 for(int i = 0;i<27;i++){ int temp = 0; for(int j = 0;j<string.length();j++){ if(string.charAt(j) == chars[i]) { temp++; } } number[i] += temp; } } public int[] getNumber(){ return number; } public char[] getChars(){ return chars; } }
HuffmanCoding
類將讀取的字母轉化成爲哈夫曼編碼,而且規定左子樹爲0,右子樹爲1public class HuffmanCoding<T> { public HuffmanNode<T> createTree(List<HuffmanNode<T>> nodes) { while (nodes.size() > 1) { Collections.sort(nodes); HuffmanNode<T> left = nodes.get(nodes.size() - 2); left.setCode(0 + ""); // 左子樹爲否(0) HuffmanNode<T> right = nodes.get(nodes.size() - 1); right.setCode(1 + ""); // 右子樹爲是(1) HuffmanNode<T> parent = new HuffmanNode<>(null, left.getWeight() + right.getWeight()); // 雙親結點的權值爲左右孩子相加 parent.setLeft(left); parent.setRight(right); nodes.remove(left); nodes.remove(right); nodes.add(parent); } return nodes.get(0); // 返回根結點 } // 廣度優先遍歷以賦值 public List<HuffmanNode<T>> BFS(HuffmanNode<T> root) { List<HuffmanNode<T>> list = new ArrayList<>(); Queue<HuffmanNode<T>> queue = new ArrayDeque<>(); if (root != null) { // 將元素入隊列 queue.offer(root); root.getLeft().setCode(root.getCode() + "0"); root.getRight().setCode(root.getCode() + "1"); } // 轉化爲0和1 while (!queue.isEmpty()) { list.add(queue.peek()); HuffmanNode<T> node = queue.poll(); // 獲取頭結點 if (node.getLeft() != null) { node.getLeft().setCode(node.getCode() + "0"); // 左爲0 } if (node.getRight() != null) { node.getRight().setCode(node.getCode() + "1"); // 右爲1 } if (node.getLeft() != null) { queue.offer(node.getLeft()); } if (node.getRight() != null) { queue.offer(node.getRight()); } } return list; } }
Huffman
從input.txt
中讀取信息,轉化爲哈夫曼編碼後將哈夫曼編碼放入output.txt
中後完成測試。public class Huffman { public static void main(String[] args) throws IOException { List<HuffmanNode<String>> list = new ArrayList<>(); List<HuffmanNode<String>> list2; List<String> list3 = new ArrayList<>(); List<String> list4 = new ArrayList<>(); List<String> list5 = new ArrayList<>(); String temp2 = "",temp3 = ""; String result=""; double num2 = 0; File file = new File("C:\\Users\\機械革命.000\\Desktop\\程序設計\\大二上\\哈夫曼\\input.txt"); ReadTxt read = new ReadTxt(); String temp = read.txtString(file); System.out.println("讀取的文件是:" + temp); int[] num = read.getNumber(); // 存放出現次數的數組 char[] chars = read.getChars(); // 存放元素的數組 for(int i = 0;i<27;i++){ System.out.print(chars[i]+":"+num[i]+" "); list.add(new HuffmanNode<>(chars[i]+"",num[i])); } Collections.sort(list); // 按照天然順序排序 System.out.println(); HuffmanCoding huffmanTree = new HuffmanCoding(); HuffmanNode<String> root = huffmanTree.createTree(list); list2 = huffmanTree.BFS(root);// 利用廣度優先遍歷遍歷整棵樹後賦值 for(int i = 0;i<list2.size();i++){ if(list2.get(i).getData()!=null) { list3.add(list2.get(i).getData()); list4.add(list2.get(i).getCode()); } } for(int i = 0;i<list2.size();i++){ num2 += list2.get(i).getWeight(); } Collections.sort(list3); System.out.println("出現的機率中第一個表明空格。"); for(int i = 0;i<list3.size();i++){ System.out.print(list3.get(i) + "出現的機率爲:" + list2.get(i).getWeight()/num2 + " \n"); } System.out.println(); for(int i = 0;i<list4.size();i++){ System.out.print(list3.get(i)+"的編碼爲:"+list4.get(i)+" \n"); } System.out.println(); for(int i = 0;i<temp.length();i++){ for(int j = 0;j<list3.size();j++){ if(temp.charAt(i) == list3.get(j).charAt(0)) { result += list4.get(j); } } } for(int i = 0;i<result.length();i++){ list5.add(result.charAt(i)+""); } while (list5.size()>0){ temp2 = temp2+"" +list5.get(0); list5.remove(0); for(int i=0;i<list4.size();i++){ if (temp2.equals(list4.get(i))) { temp3 = temp3+""+list3.get(i); temp2 = ""; } } } System.out.println(); System.out.println("編碼前:" + temp); System.out.println("編碼後爲:\n"+ result); System.out.println("解碼後:"+"\n"+temp3); File file2 =new File("C:\\Users\\機械革命.000\\Desktop\\程序設計\\大二上\\哈夫曼\\output.txt"); Writer out =new FileWriter(file2); out.write(result); // 將哈夫曼編碼放入output.txt中 out.close(); } }
Collections.sort
方法時不瞭解該方法,也不瞭解如何使用。該方法是一個排序方法,升序排序。java
Queue.offer
方法不瞭解。