huffman mintree
This commit is contained in:
parent
afee59b093
commit
bee1b816cd
|
@ -0,0 +1,72 @@
|
||||||
|
package com.com.brainbaking.greedy;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Huffman {
|
||||||
|
|
||||||
|
private final String toEncode;
|
||||||
|
private final Node root;
|
||||||
|
|
||||||
|
public Huffman(String toEncode) {
|
||||||
|
this.toEncode = toEncode;
|
||||||
|
|
||||||
|
root = buildMinRoot(buildQueue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node buildMinRoot(Queue<Node> nodes) {
|
||||||
|
Node root = null;
|
||||||
|
|
||||||
|
while(nodes.size() > 1) {
|
||||||
|
Node first = nodes.poll();
|
||||||
|
Node second = nodes.poll();
|
||||||
|
|
||||||
|
root = new Node(first, second);
|
||||||
|
nodes.add(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in geval van maar 1 karakter
|
||||||
|
return root == null ? nodes.poll() : root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Queue<Node> buildQueue() {
|
||||||
|
Set<Integer> chars = buildCharSet();
|
||||||
|
Queue<Node> tree = new PriorityQueue<>();
|
||||||
|
|
||||||
|
for(Integer character : chars) {
|
||||||
|
int frequency = (int) toEncode.chars().filter(c -> c == character).count();
|
||||||
|
tree.add(new Node(character, frequency));
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Integer> buildCharSet() {
|
||||||
|
return toEncode.chars().boxed().collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode() {
|
||||||
|
Map<Character, String> encodeMap = new HashMap<>();
|
||||||
|
buildEncodedMap(root, encodeMap, "");
|
||||||
|
|
||||||
|
String encoded = "";
|
||||||
|
for(int i = 0; i < toEncode.length(); i++) {
|
||||||
|
encoded += encodeMap.get(toEncode.charAt(i));
|
||||||
|
}
|
||||||
|
return encoded;
|
||||||
|
|
||||||
|
// wat is hier mis mee?
|
||||||
|
//return toEncode.chars().mapToObj(c -> encodeMap.get(c)).collect(Collectors.joining());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildEncodedMap(Node node, Map<Character,String> map, String encoded) {
|
||||||
|
if(node.isRoot()) {
|
||||||
|
// in geval van maar 1 karakter
|
||||||
|
map.put(node.getCharacter(), encoded.equals("") ? "0" : encoded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildEncodedMap(node.getLeft(), map, encoded + "0");
|
||||||
|
buildEncodedMap(node.getRight(), map, encoded + "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.com.brainbaking.greedy;
|
||||||
|
|
||||||
|
public class Node implements Comparable<Node> {
|
||||||
|
|
||||||
|
private final char character;
|
||||||
|
private final int frequency;
|
||||||
|
|
||||||
|
private Node left;
|
||||||
|
private Node right;
|
||||||
|
|
||||||
|
public boolean isRoot() {
|
||||||
|
return left == null && right == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getCharacter() {
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFrequency() {
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(Node left, Node right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
this.character = '-';
|
||||||
|
this.frequency = left.getFrequency() + right.getFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(Integer character, int frequency) {
|
||||||
|
this.character = (char) character.intValue();
|
||||||
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Node o) {
|
||||||
|
return frequency - o.frequency;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.brainbaking.greedy;
|
||||||
|
|
||||||
|
import com.com.brainbaking.greedy.Huffman;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
|
public class HuffmanTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void huffman_OnlyOnCharacter() {
|
||||||
|
Huffman huffman = new Huffman("aaa");
|
||||||
|
|
||||||
|
String result = huffman.encode();
|
||||||
|
|
||||||
|
assertEquals("000", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void huffman_charAFrequences5TimesButBAndCOnlyOnce() {
|
||||||
|
Huffman huffman = new Huffman("baaaaac");
|
||||||
|
|
||||||
|
String result = huffman.encode();
|
||||||
|
|
||||||
|
assertEquals("001111101", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void huffmanEncoded() {
|
||||||
|
Huffman huffman = new Huffman("hallo dit is een test wasda jong");
|
||||||
|
|
||||||
|
String result = huffman.encode();
|
||||||
|
|
||||||
|
assertEquals("110001101100110011000111101110100101111010000111001001011011101000100001011111001110100010111101111011111000011001110", result);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue