//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();
}
}