Skip to content

Commit 5c5819a

Browse files
Added the Huffman Coding using java
1 parent d8ddb07 commit 5c5819a

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
2+
import java.util.HashMap;
3+
import java.util.Map;
4+
import java.util.PriorityQueue;
5+
6+
// A node in the Huffman Tree
7+
class HuffmanNode implements Comparable<HuffmanNode> {
8+
int frequency;
9+
char character;
10+
HuffmanNode left;
11+
HuffmanNode right;
12+
13+
// Compare nodes based on frequency. Used by the PriorityQueue.
14+
@Override
15+
public int compareTo(HuffmanNode other) {
16+
return this.frequency - other.frequency;
17+
}
18+
}
19+
20+
public class HuffmanCoding {
21+
22+
private static Map<Character, String> huffmanCodes = new HashMap<>();
23+
private static HuffmanNode root;
24+
25+
/**
26+
* Builds the Huffman Tree and generates codes.
27+
* @param text The input string to be encoded.
28+
*/
29+
public static void buildTree(String text) {
30+
// 1. Calculate character frequencies
31+
Map<Character, Integer> frequencies = new HashMap<>();
32+
for (char character : text.toCharArray()) {
33+
frequencies.put(character, frequencies.getOrDefault(character, 0) + 1);
34+
}
35+
36+
// 2. Create leaf nodes and add them to a priority queue
37+
PriorityQueue<HuffmanNode> pq = new PriorityQueue<>();
38+
for (Map.Entry<Character, Integer> entry : frequencies.entrySet()) {
39+
HuffmanNode node = new HuffmanNode();
40+
node.character = entry.getKey();
41+
node.frequency = entry.getValue();
42+
node.left = null;
43+
node.right = null;
44+
pq.add(node);
45+
}
46+
47+
// Handle case of single unique character
48+
if (pq.size() == 1) {
49+
HuffmanNode singleNode = pq.peek();
50+
huffmanCodes.put(singleNode.character, "0");
51+
root = singleNode;
52+
return;
53+
}
54+
55+
// 3. Build the tree by merging nodes
56+
while (pq.size() > 1) {
57+
// Get the two nodes with the lowest frequency
58+
HuffmanNode left = pq.poll();
59+
HuffmanNode right = pq.poll();
60+
61+
// Create a new internal node
62+
HuffmanNode internalNode = new HuffmanNode();
63+
internalNode.frequency = left.frequency + right.frequency;
64+
internalNode.character = '-'; // Internal nodes have no character
65+
internalNode.left = left;
66+
internalNode.right = right;
67+
68+
// Add the new node back to the queue
69+
pq.add(internalNode);
70+
}
71+
72+
// The remaining node is the root of the tree
73+
root = pq.poll();
74+
75+
// 4. Generate Huffman codes by traversing the tree
76+
generateCodes(root, "");
77+
}
78+
79+
/**
80+
* Recursively traverses the tree to generate codes for each character.
81+
* @param node The current node in the traversal.
82+
* @param code The binary code generated so far.
83+
*/
84+
private static void generateCodes(HuffmanNode node, String code) {
85+
if (node == null) {
86+
return;
87+
}
88+
89+
// If it's a leaf node, it contains a character
90+
if (node.left == null && node.right == null) {
91+
huffmanCodes.put(node.character, code);
92+
return;
93+
}
94+
95+
// Traverse left (append '0') and right (append '1')
96+
generateCodes(node.left, code + "0");
97+
generateCodes(node.right, code + "1");
98+
}
99+
100+
/**
101+
* Encodes the given text using the generated Huffman codes.
102+
* @param text The text to encode.
103+
* @return The encoded binary string.
104+
*/
105+
public static String encode(String text) {
106+
StringBuilder encodedText = new StringBuilder();
107+
for (char character : text.toCharArray()) {
108+
encodedText.append(huffmanCodes.get(character));
109+
}
110+
return encodedText.toString();
111+
}
112+
113+
/**
114+
* Decodes the given binary string using the Huffman Tree.
115+
* @param encodedText The binary string to decode.
116+
* @return The original decoded text.
117+
*/
118+
public static String decode(String encodedText) {
119+
StringBuilder decodedText = new StringBuilder();
120+
HuffmanNode current = root;
121+
for (int i = 0; i < encodedText.length(); i++) {
122+
char bit = encodedText.charAt(i);
123+
if (bit == '0') {
124+
current = current.left;
125+
} else {
126+
current = current.right;
127+
}
128+
129+
// If it's a leaf node, we found a character
130+
if (current.left == null && current.right == null) {
131+
decodedText.append(current.character);
132+
current = root; // Return to the root for the next character
133+
}
134+
}
135+
return decodedText.toString();
136+
}
137+
138+
public static void main(String[] args) {
139+
String text = "huffman coding is a lossless data compression algorithm";
140+
141+
System.out.println("Original Text: " + text);
142+
System.out.println("----------------------------------------");
143+
144+
// Build the Huffman Tree and generate codes
145+
buildTree(text);
146+
147+
// Print the Huffman codes for each character
148+
System.out.println("Huffman Codes:");
149+
for (Map.Entry<Character, String> entry : huffmanCodes.entrySet()) {
150+
System.out.println("'" + entry.getKey() + "': " + entry.getValue());
151+
}
152+
System.out.println("----------------------------------------");
153+
154+
// Encode the text
155+
String encodedText = encode(text);
156+
System.out.println("Encoded Text: " + encodedText);
157+
System.out.println("----------------------------------------");
158+
159+
// Decode the text
160+
String decodedText = decode(encodedText);
161+
System.out.println("Decoded Text: " + decodedText);
162+
System.out.println("----------------------------------------");
163+
164+
// Verification
165+
System.out.println("Verification (Original equals Decoded): " + text.equals(decodedText));
166+
}
167+
}

0 commit comments

Comments
 (0)