Skip to content

Instantly share code, notes, and snippets.

@mrniko
Created June 22, 2015 06:19
Show Gist options
  • Save mrniko/6d2f549c3aecb42d5f12 to your computer and use it in GitHub Desktop.
Save mrniko/6d2f549c3aecb42d5f12 to your computer and use it in GitHub Desktop.
Huffman service
import java.util.BitSet;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.stereotype.Service;
public class HuffmanService {
public final Queue<Node> q = new PriorityQueue<>(100, new FrequencyComparator());
public final Map<Character, String> charToCode = new HashMap<>();
public final Map<String, Character> codeToChar = new HashMap<>();
public HuffmanServiceImpl() {
buildDict();
}
private void buildDict() {
HashMap<Character, Integer> dict = new HashMap<Character, Integer>();
dict.put('0', 10);
dict.put('1', 10);
dict.put('2', 10);
dict.put('3', 10);
dict.put('4', 10);
dict.put('5', 10);
dict.put('6', 10);
dict.put('7', 10);
dict.put('8', 10);
dict.put('9', 10);
int n = 0;
for (Character c : dict.keySet()) {
q.add(new Node(c, dict.get(c)));
n++;
}
// Identify the root of the tree
Node root = huffman(n);
// Build the table for the variable length codes
buildTable(root);
}
public String compress(String s) {
BitSet bs = new BitSet();
int m = 0;
for (int i = 0; i < s.length(); i++) {
String code = charToCode.get(s.charAt(i));
if (code == null) {
throw new IllegalStateException("Can't find code for " + s.charAt(i));
}
for (Character ch : charToCode.get(s.charAt(i)).toCharArray()) {
bs.set(m, ch == '1');
m++;
}
}
return new String(Hex.encode(bs.toByteArray()));
}
public String decompress(String str) {
BitSet bs = BitSet.valueOf(Hex.decode(str));
String temp = new String();
String result = new String();
for (int i = 0; i < bs.length(); i++) {
temp = temp + (bs.get(i) ? '1' : '0');
if (codeToChar.containsKey(temp)) {
result = result + codeToChar.get(temp);
temp = new String();
}
}
return result;
}
private Node huffman(int n) {
Node x, y;
for (int i = 1; i <= n - 1; i++) {
Node z = new Node();
z.left = x = q.poll();
z.right = y = q.poll();
z.freq = x.freq + y.freq;
q.add(z);
}
return q.poll();
}
private void buildTable(Node root) {
postorder(root, new String());
}
// This method is used to traverse from ROOT-to-LEAVES
private void postorder(Node n, String s) {
if (n == null)
return;
postorder(n.left, s + "0");
postorder(n.right, s + "1");
// Visit only nodes with keys
if (n.alpha != 0) {
System.out.println("\'" + n.alpha + "\' -> " + s);
charToCode.put(n.alpha, s);
codeToChar.put(s, n.alpha);
}
}
}
class Node {
public char alpha;
public int freq;
public Node left, right;
public Node(char a, int f) {
alpha = a;
freq = f;
}
public Node() {
}
public String toString() {
return alpha + " " + freq;
}
}
class FrequencyComparator implements Comparator<Node> {
public int compare(Node a, Node b) {
int freqA = a.freq;
int freqB = b.freq;
return freqA - freqB;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment