实现时参考了博客
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
方法不了解。