算法 5.5 霍夫曼压缩和LZW压缩

//Huffman
import edu.princeton.cs.algs4.*;
import edu.princeton.cs.algs4.MinPQ;

public class Huffman {
    private final int R = 256;
    private class Node implements  Comparable<Node>{
        int fre;
        char ch;
        Node left, right;

        public Node(char ch, int fre, Node left, Node right) {
            this.fre = fre;
            this.ch = ch;
            this.left = left;
            this.right = right;
        }

        @Override
        public int compareTo(Node that) {
            return this.fre = that.fre;
        }

        public boolean isLeaf() {
            return left == null && right == null;
        }
    }

    public void compress() {
        String s = BinaryStdIn.readString();
        char[] input = s.toCharArray(); // 将字符串转换为字符数组,便于后面的频率统计
        int[] fre = new int[R];
        for (int i = 0; i < input.length;i++) {
            fre[input[i]]++;
        }

        Node root = buildTree(fre);
        String[] st = buildCode(root);
        writeTree(root);
        BinaryStdOut.write(input.length);

        for (int i = 0; i < input.length;i++) {
            String code = st[input[i]];
            for (int j = 0;j < code.length();j++) {
                if (code.charAt(j) == '1') BinaryStdOut.write(true);
                else BinaryStdOut.write(false);
            }
        }
        BinaryStdOut.close();
    }

    private Node readTree() {
        if (BinaryStdIn.readBoolean()) new Node(BinaryStdIn.readChar(), 0, null, null);
        else return new Node('\0', 0, readTree(), readTree());
    }

    private void writeTree(Node root) {
        if (root.isLeaf()) {
            BinaryStdOut.write(true);
            BinaryStdOut.write(root.ch);
            return;
        }
        BinaryStdOut.write(false);
        writeTree(root.left);
        writeTree(root.right);
    }

    private Node buildTree(int[] fre) {
        MinPQ<Node> pq = new MinPQ<Node>();
        for (char i = 0;i < R;i++) { // 用char而不是int的好处在于初始化Node时可以直接用i而不用转换类型
            pq.insert(new Node(i, fre[i], null, null));
        }

        while (pq.size() > 1) { //不能用isempty函数,因为最后要剩一个
            Node a = pq.delMin();
            Node b = pq.delMin();
            Node parent = new Node('\0', a.fre + b.fre, a, b);
            pq.insert(parent);
        }
        return pq.delMin();
    }

    private String[] buildCode(Node root) {
        String[] st = new String[R];
        buildCode(st, root, "");
        return st;
    }

    private void buildCode(String[] st, Node x, String s) {
        if (x.isLeaf()) {
            st[x.ch] = s;
            return;
        }
        buildCode(st, x.left, s + '0');
        buildCode(st, x.right, s + '1');
    }

    public void expand() {
        Node root = readTree();
        int N = BinaryStdIn.readInt();
        for (int i = 0; i < N; i++) {
            Node x = root;
            while (!x.isLeaf()) {
                if (BinaryStdIn.readBoolean()) x = x.right;
                else x = x.left;
            }
            BinaryStdOut.write(x.ch);
        }
        BinaryStdOut.close();
    }


}
//LZW
import edu.princeton.cs.algs4.*;
public class LZW {
    private static final int R = 256;
    private static final int Width = 12;
    private static final int Max = 4096;

    public void compress() {
        String txt = BinaryStdIn.readString();
        TST<Integer> st = new TST<>();
        for (int i = 0;i < R;i++) {
            st.put("" + (char) i, i);
        }
        int newCode = R + 1;

        while (txt.length() > 0) {
            String s = st.longestPrefixOf(txt);
            BinaryStdOut.write(s, Width);

            int t =s.length();
            if (t < txt.length() && newCode < Max) {
                st.put(txt.substring(0, t + 1), newCode++);
            }
            txt = txt.substring(t);
        }
        BinaryStdOut.write(R, Width);
        BinaryStdOut.close();
    }

    public void expand() {
        String[] st = new String[Max];
        int i;

        for (i = 0; i < R ;i++) {
            st[i] = "" + (char) i;
        }
        st[i++] = " ";

        int codeWord = BinaryStdIn.readInt(Width);
        String val = st[codeWord];
        while (true) {
            BinaryStdOut.write(val);
            codeWord = BinaryStdIn.readInt(Width);
            if (codeWord == R) break;
            String s = st[codeWord];
            if (i == codeWord) {
                s = val + val.charAt(0);
            }
            if (i < Max) {
                st[i++] = val + s.charAt(0);
            }
            val = s;
        }
        BinaryStdOut.close();
    }
}

猜你喜欢

转载自blog.csdn.net/winter_wu_1998/article/details/80357297
5.5