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 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 { 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); } } }