Repository navigation
Expand file tree
/
Copy pathHuffmanCoder.java
More file actions
144 lines (97 loc) · 3.55 KB
/
Copy pathHuffmanCoder.java
File metadata and controls
144 lines (97 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package HuffmanCodingGreedyAlgorithm;
import java.util.*;
public class HuffmanCoder {
HashMap<Character , String> encoder;
HashMap<String , Character> decoder;
private class Node implements Comparable<Node>{
Character data;
int cost; // this is frequency
Node left;
Node right;
public Node(Character data, int cost) {
this.data = data;
this.cost = cost;
this.left = null;
this.right = null;
}
// for comparing two nodes for min heap
@Override
public int compareTo(Node other) {
return this.cost - other.cost;
}
}
// in this constructor we are going to form the tree that i have mentioned in the notes
public HuffmanCoder (String feeder) throws Exception{
// step 1 : make a map
HashMap<Character , Integer> fmap = new HashMap<>();
for (int i = 0 ; i < feeder.length() ; i++){
char currentCharacter = feeder.charAt(i);
if (fmap.containsKey(currentCharacter)){
int originalValue = fmap.get(currentCharacter);
originalValue+=1;
fmap.put(currentCharacter , originalValue);
}else{
fmap.put(currentCharacter , 1);
}
}
// step 2 : create a min heap
Heap<Node> minheap = new Heap<>();
Set<Map.Entry<Character , Integer>> entrySet = fmap.entrySet();
for (Map.Entry<Character , Integer> entry : entrySet){
Node node = new Node(entry.getKey() , entry.getValue());
minheap.insert(node);
}
// step 3 : remove two elements till the size of minheap comes to 1
while (minheap.size() != 1){
Node first = minheap.remove();
Node second = minheap.remove();
// remove two elements
Node newNode = new Node('\0' , first.cost + second.cost);
newNode.left = first;
newNode.right = second;
// add in the minheap
minheap.insert(newNode);
}
Node fullTree = minheap.remove();
this.encoder = new HashMap<>();
this.decoder = new HashMap<>();
this.initEncoderDecoder(fullTree , "");
}
private void initEncoderDecoder(Node node , String outPutSoFar){
if (node == null){
return;
}
// by recursion we are going down to leaf node
if (node.left == null && node.right == null){
// adding data first then output so far in encoder
this.encoder.put(node.data , outPutSoFar);
// adding outputsofar then the data in decoder
this.decoder.put(outPutSoFar , node.data);
}
// for left side taking 0
initEncoderDecoder(node.left , outPutSoFar+"0");
// for right side raking 1
initEncoderDecoder(node.right , outPutSoFar+"1");
}
// for encoding the message
public String encoding(String source){
String ans = "";
for (int i = 0 ; i < source.length() ; i++){
ans += encoder.get(source.charAt(i));
}
return ans;
}
// for decoding the message
public String decode(String codedString) {
String key = "";
String ans = "";
for(int i=0; i<codedString.length(); i++) {
key = key + codedString.charAt(i);
if(decoder.containsKey(key)) {
ans = ans + decoder.get(key);
key = "";
}
}
return ans;
}
}