Created
June 22, 2015 06:19
-
-
Save mrniko/6d2f549c3aecb42d5f12 to your computer and use it in GitHub Desktop.
Huffman service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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