一、霍夫曼压缩:
1、霍夫曼编码是一个两轮算法。
2、对于任意前缀码,编码后的比特字符串的长度等于相应单词查找树的加权外部路径长度。
3、给定一个含有r个符号的集合和它们的频率,霍夫曼算法所构造的前缀码是最优的。
4、霍夫曼压缩实现:
import javax.naming.BinaryRefAddr;
//霍夫曼压缩
public class Huffman
{
private static int R = 256;//ASCII字母表
public static void compress()
{
String s = BinarySdIn.readString();
char[] input = s.toCharArray();
//统计频率
int[] freq = new int[R];
for (int i = 0; i < input.length; i++)
freq[input[i]]++;
//构造霍夫曼树
Node root = buildTrie(freq);
//构造编译表
String[] st = new String[R];
buildCode(st, root, "");
//递归地打印解码用的单词查找树
writeTrie(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 static Node buildTrie(int[] freq)
{
MinPQ<Node> pq = new MinPQ<Node>();
for (char c = 0; c < R; c++)
if (freq[c] > 0)
pq.insert(new Node(c, frep[c], null, null));
while (pq.size() > 1)
{
Node x = pq.delMin();
Node y = pq.delMin();
Node parent = new Node('\0', x.freq + y.freq, x, y);
pq.insert(parent);
}
return pq.delMin();
}
}
二、LZW算法实现:
public class LZW
{
private static final int R = 256;
private static final int L = 4096;
private static final int W = 12;
public static void compress()
{
String input = BinaryStdIn.readString();
TST<Integer> st = new TST<Integer>();
for (int i = 0; i < R; i++)
st.put("" + (char) i, i);
int code = R + 1;
while (input.length() > 0)
{
String s = st.longestPrefixOf(input);//找到匹配最长前缀
BinaryStdOut.write(st.get(s), W);//打印出s的编码
int t = s.length();
if (t < input.length() && code < L)
st.put(input.substring(0, t + 1), code++);
input = input.substring(t);
}
BinaryStdOut.write(R, W);
BinaryStdOut.close();
}
public static void expand()
{
String[] st = new String[L];
int i;
for (i = 0; i < R; i++)
st[i] = "" + (char) i;
int codeword = BinaryStdIn.readInt(W);
String val = st[codeword];
while(true)
{
BinaryStdOut.write(val);
codeword = BinaryStdIn.readInt(W);
if (codeword == R) break;
String s = st[codeword];
if (i == codeword)
s = val + val.charAt(0);
if (i < L)
st[i++] = val + s.charAt(0);
val = s;
}
BinaryStdOut.close();
}
}