summaryrefslogtreecommitdiff
path: root/p3/HuffmanCode.java
diff options
context:
space:
mode:
Diffstat (limited to 'p3/HuffmanCode.java')
-rw-r--r--p3/HuffmanCode.java117
1 files changed, 117 insertions, 0 deletions
diff --git a/p3/HuffmanCode.java b/p3/HuffmanCode.java
new file mode 100644
index 0000000..8691ce8
--- /dev/null
+++ b/p3/HuffmanCode.java
@@ -0,0 +1,117 @@
+import java.util.*;
+import java.io.*;
+
+public class HuffmanCode {
+
+ public HuffmanNode root;
+
+ // Constructor that builds the Huffman tree from an array of frequencies
+ public HuffmanCode(int[] frequencies) {
+ Queue<HuffmanNode> nodes = new PriorityQueue<>();
+ for (int i = 0; i < frequencies.length; i++) {
+ if (frequencies[i] > 0) {
+ nodes.add(new HuffmanNode((char) i, frequencies[i]));
+ }
+ }
+ while (nodes.size() > 1) {
+ HuffmanNode left = nodes.remove();
+ HuffmanNode right = nodes.remove();
+ HuffmanNode branch = new HuffmanNode('\0', left.freq + right.freq, left, right);
+ nodes.add(branch);
+ }
+ this.root = nodes.isEmpty() ? null : nodes.remove();
+ }
+
+ // Constructor that reads the Huffman tree from a Scanner
+ public HuffmanCode(Scanner input) {
+ this.root = new HuffmanNode('\0', 0); // Initialize root with a dummy node
+ while (input.hasNextLine()) {
+ int character = Integer.parseInt(input.nextLine());
+ String path = input.nextLine();
+ addNode(character, path);
+ }
+ }
+
+ // Adds a node to the Huffman tree based on the given path
+ private void addNode(int character, String path) {
+ HuffmanNode current = root;
+ for (int i = 0; i < path.length(); i++) {
+ char direction = path.charAt(i);
+ if (direction == '0') {
+ if (current.left == null) {
+ if (i == path.length() - 1) {
+ current.left = new HuffmanNode((char) character, 1); // Final node
+ } else {
+ current.left = new HuffmanNode('\0', 0); // Create a dummy node if it doesn't exist
+ }
+ }
+ current = current.left;
+ } else if (direction == '1') {
+ if (current.right == null) {
+ if (i == path.length() - 1) {
+ current.right = new HuffmanNode((char) character, 1); // Final node
+ } else {
+ current.right = new HuffmanNode('\0', 0); // Create a dummy node if it doesn't exist
+ }
+ }
+ current = current.right;
+ }
+ }
+ }
+
+ // Saves the Huffman tree to the given output stream in standard format
+ public void save(PrintStream output) {
+ save(output, this.root, "");
+ }
+
+ private void save(PrintStream output, HuffmanNode head, String path) {
+ if (head != null) {
+ if (head.data != '\0') {
+ output.println((int) head.data);
+ output.println(path);
+ }
+ save(output, head.left, path + "0");
+ save(output, head.right, path + "1");
+ }
+ }
+
+ // Translates bits from the input stream to characters and writes them to the output stream
+ public void translate(BitInputStream input, PrintStream output) {
+ HuffmanNode current = root;
+ while (input.hasNextBit()) {
+ int bit = input.nextBit();
+ if (bit == 0) {
+ current = current.left;
+ } else {
+ current = current.right;
+ }
+ if (current.left == null && current.right == null) { // Leaf node
+ output.print(current.data);
+ current = root; // Restart for next character
+ }
+ }
+ }
+
+ // Inner class representing a node in the Huffman tree
+ private static class HuffmanNode implements Comparable<HuffmanNode> {
+ public char data;
+ public int freq;
+ public HuffmanNode left;
+ public HuffmanNode right;
+
+ public HuffmanNode(char data, int frequency) {
+ this(data, frequency, null, null);
+ }
+
+ public HuffmanNode(char data, int frequency, HuffmanNode left, HuffmanNode right) {
+ this.data = data;
+ this.freq = frequency;
+ this.left = left;
+ this.right = right;
+ }
+
+ public int compareTo(HuffmanNode other) {
+ return Integer.compare(this.freq, other.freq);
+ }
+ }
+}