(六)哈夫曼树编码

133 阅读1分钟

算法导论实验(六)哈夫曼编码源码:

public class Node {
    public int key;
    public char data;
    public Node left;
    public Node right;
}
public class Huffman {
    public static void main(String[] args) {
        List<Character> data=null;
        Map<Character,Integer> map=new HashMap<>();
        try {
            data= getData();    //从data.txt文件中读取数据存放在data中
            for(char c:data)
                map.put(c,map.getOrDefault(c,0)+1); //统计各个字符的频率
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        Node root=HuffmanBuild(map);
        Map<Character,String> encodeData=new HashMap<>();
        encode(root,encodeData,new StringBuilder());
        List<String> writeData=new ArrayList<>();
        int encodeLen=0;
        for(char c:data){
            writeData.add(encodeData.get(c));
            encodeLen+=encodeData.get(c).length();
        }
        write(writeData);
        int oldLen=0;
        if(map.size()==1)
            oldLen=1*data.size();
        else
            oldLen= (int) ((Math.ceil(Math.log(map.size())/Math.log(2)))*data.size());
        DecimalFormat df = new DecimalFormat( "0.00");
        System.out.println("压缩率:"+df.format(100*(double)encodeLen/ oldLen)+"%");

    }
    static public void encode(Node root,Map<Character,String> map,StringBuilder sb){
        if(root.left==null&&root.right==null){
            map.put(root.data,sb.toString());
            return;
        }
        sb.append("0");
        encode(root.left,map,sb);
        sb.deleteCharAt(sb.length()-1);
        sb.append("1");
        encode(root.right,map,sb);
        sb.deleteCharAt(sb.length()-1);
    }
    static public Node HuffmanBuild(Map<Character,Integer> map){
        PriorityQueue<Node> pq=new PriorityQueue<>((o1,o2)->o1.key-o2.key);
        Set<Map.Entry<Character, Integer>> entries = map.entrySet();
        for(Map.Entry<Character,Integer> entry:entries){
            Node node=new Node();
            node.data=entry.getKey();
            node.key=entry.getValue();
            pq.offer(node);
        }
        int n=pq.size();
        for(int i=0;i<n-1;i++){
            Node z=new Node();
            z.left=pq.poll();
            z.right=pq.poll();
            z.key=z.left.key+z.right.key;
            pq.offer(z);
        }
        return pq.poll();
    }
    public static List getData() throws FileNotFoundException {
       List<Character> list=new ArrayList<>();
       try(InputStream in=new FileInputStream("src/algorithm/project5/data.txt")){
           int n;
           while((n=in.read())!=-1){
               char c=(char)n;
               list.add(c);
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
       return list;
    }
    public static  void write(List<String> data){
        File file = new File("src/algorithm/project5/encode.txt");
        if(!file.exists()){
            file.mkdir();
        }
        try(Writer out =new FileWriter(file)) {
            for(int i=0;i<data.size();i++){
                out.write(data.get(i));
                out.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}