Huffman Coding using Priority Queue
Prerequisite: Greedy Algorithms | Set 3 (Huffman Coding), priority_queue::push() and priority_queue::pop() in C++ STL
Given a char array ch[] and frequency of each character as freq[]. The task is to find Huffman Codes for every character in ch[] using Priority Queue.
Example
Input: ch[] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ }, freq[] = { 5, 9, 12, 13, 16, 45 }
Output:
f 0
c 100
d 101
a 1100
b 1101
e 111
Approach:
- Push all the characters in ch[] mapped to corresponding frequency freq[] in priority queue.
- To create Huffman Tree, pop two nodes from priority queue.
- Assign two popped node from priority queue as left and right child of new node.
- Push the new node formed in priority queue.
- Repeat all above steps until size of priority queue becomes 1.
- Traverse the Huffman Tree (whose root is the only node left in the priority queue) to store the Huffman Code
- Print all the stored Huffman Code for every character in ch[].
Below is the implementation of the above approach:
C++
// C++ Program for Huffman Coding // using Priority Queue #include <iostream> #include <queue> using namespace std; // Maximum Height of Huffman Tree. #define MAX_SIZE 100 class HuffmanTreeNode { public : // Stores character char data; // Stores frequency of // the character int freq; // Left child of the // current node HuffmanTreeNode* left; // Right child of the // current node HuffmanTreeNode* right; // Initializing the // current node HuffmanTreeNode( char character, int frequency) { data = character; freq = frequency; left = right = NULL; } }; // Custom comparator class class Compare { public : bool operator()(HuffmanTreeNode* a, HuffmanTreeNode* b) { // Defining priority on // the basis of frequency return a->freq > b->freq; } }; // Function to generate Huffman // Encoding Tree HuffmanTreeNode* generateTree(priority_queue<HuffmanTreeNode*, vector<HuffmanTreeNode*>, Compare> pq) { // We keep on looping till // only one node remains in // the Priority Queue while (pq.size() != 1) { // Node which has least // frequency HuffmanTreeNode* left = pq.top(); // Remove node from // Priority Queue pq.pop(); // Node which has least // frequency HuffmanTreeNode* right = pq.top(); // Remove node from // Priority Queue pq.pop(); // A new node is formed // with frequency left->freq // + right->freq // We take data as '$' // because we are only // concerned with the // frequency HuffmanTreeNode* node = new HuffmanTreeNode( '$' , left->freq + right->freq); node->left = left; node->right = right; // Push back node // created to the // Priority Queue pq.push(node); } return pq.top(); } // Function to print the // huffman code for each // character. // It uses arr to store the codes void printCodes(HuffmanTreeNode* root, int arr[], int top) { // Assign 0 to the left node // and recur if (root->left) { arr[top] = 0; printCodes(root->left, arr, top + 1); } // Assign 1 to the right // node and recur if (root->right) { arr[top] = 1; printCodes(root->right, arr, top + 1); } // If this is a leaf node, // then we print root->data // We also print the code // for this character from arr if (!root->left && !root->right) { cout << root->data << " " ; for ( int i = 0; i < top; i++) { cout << arr[i]; } cout << endl; } } void HuffmanCodes( char data[], int freq[], int size) { // Declaring priority queue // using custom comparator priority_queue<HuffmanTreeNode*, vector<HuffmanTreeNode*>, Compare> pq; // Populating the priority // queue for ( int i = 0; i < size; i++) { HuffmanTreeNode* newNode = new HuffmanTreeNode(data[i], freq[i]); pq.push(newNode); } // Generate Huffman Encoding // Tree and get the root node HuffmanTreeNode* root = generateTree(pq); // Print Huffman Codes int arr[MAX_SIZE], top = 0; printCodes(root, arr, top); } // Driver Code int main() { char data[] = { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' }; int freq[] = { 5, 9, 12, 13, 16, 45 }; int size = sizeof (data) / sizeof (data[0]); HuffmanCodes(data, freq, size); return 0; } |
Java
import java.util.*; class HuffmanTreeNode implements Comparable<HuffmanTreeNode> { // Stores character char data; // Stores frequency of the character int freq; // Left child of the current node HuffmanTreeNode left; // Right child of the current node HuffmanTreeNode right; public HuffmanTreeNode( char character, int frequency) { data = character; freq = frequency; left = right = null ; } public int compareTo(HuffmanTreeNode other) { return freq - other.freq; } } class HuffmanCodes { // Maximum Height of Huffman Tree. static final int MAX_SIZE = 100 ; // Function to print the huffman code for each // character. It uses arr to store the codes static void printCodes(HuffmanTreeNode root, int [] arr, int top) { // Assign 0 to the left node and recur if (root.left != null ) { arr[top] = 0 ; printCodes(root.left, arr, top + 1 ); } // Assign 1 to the right node and recur if (root.right != null ) { arr[top] = 1 ; printCodes(root.right, arr, top + 1 ); } // If this is a leaf node, then we print root.data // We also print the code for this character from // arr if (root.left == null && root.right == null ) { System.out.print(root.data + " " ); for ( int i = 0 ; i < top; ++i) { System.out.print(arr[i]); } System.out.println(); } } // Function to generate Huffman Encoding Tree static HuffmanTreeNode generateTree(PriorityQueue<HuffmanTreeNode> pq) { // We keep on looping till only one node remains in // the Priority Queue while (pq.size() != 1 ) { // Node which has least frequency HuffmanTreeNode left = pq.poll(); // Node which has least frequency HuffmanTreeNode right = pq.poll(); // A new node is formed with frequency left.freq // + right.freq We take data as '$' because we // are only concerned with the frequency HuffmanTreeNode node = new HuffmanTreeNode( '$' , left.freq + right.freq); node.left = left; node.right = right; // Push back node created to the Priority Queue pq.add(node); } return pq.poll(); } // Function to generate Huffman Codes static void HuffmanCodes( char [] data, int [] freq, int size) { // Declaring priority queue using custom comparator PriorityQueue<HuffmanTreeNode> pq = new PriorityQueue<>(); // Populating the priority queue for ( int i = 0 ; i < size; i++) { HuffmanTreeNode newNode = new HuffmanTreeNode(data[i], freq[i]); pq.add(newNode); } // Generate Huffman Encoding Tree and get the root // node HuffmanTreeNode root = generateTree(pq); // Print Huffman Codes int [] arr = new int [MAX_SIZE]; int top = 0 ; printCodes(root, arr, top); } // Driver Code public static void main(String[] args) { char [] data = { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' }; int [] freq = { 5 , 9 , 12 , 13 , 16 , 45 }; int size = data.length; // Function call HuffmanCodes(data, freq, size); } } |
Python3
import queue # Maximum Height of Huffman Tree. MAX_SIZE = 100 class HuffmanTreeNode: def __init__( self , character, frequency): # Stores character self .data = character # Stores frequency of the character self .freq = frequency # Left child of the current node self .left = None # Right child of the current node self .right = None def __lt__( self , other): return self .freq < other.freq # Custom comparator class class Compare: def __call__( self , a, b): # Defining priority on the basis of frequency return a.freq > b.freq # Function to generate Huffman Encoding Tree def generateTree(pq): # We keep on looping till only one node remains in the Priority Queue while pq.qsize() ! = 1 : # Node which has least frequency left = pq.get() # Node which has least frequency right = pq.get() # A new node is formed with frequency left.freq + right.freq # We take data as '$' because we are only concerned with the frequency node = HuffmanTreeNode( '$' , left.freq + right.freq) node.left = left node.right = right # Push back node created to the Priority Queue pq.put(node) return pq.get() # Function to print the huffman code for each character. # It uses arr to store the codes def printCodes(root, arr, top): # Assign 0 to the left node and recur if root.left: arr[top] = 0 printCodes(root.left, arr, top + 1 ) # Assign 1 to the right node and recur if root.right: arr[top] = 1 printCodes(root.right, arr, top + 1 ) # If this is a leaf node, then we print root.data # We also print the code for this character from arr if not root.left and not root.right: print (root.data, end = ' ' ) for i in range (top): print (arr[i], end = '') print () def HuffmanCodes(data, freq, size): # Declaring priority queue using custom comparator pq = queue.PriorityQueue() # Populating the priority queue for i in range (size): newNode = HuffmanTreeNode(data[i], freq[i]) pq.put(newNode) # Generate Huffman Encoding Tree and get the root node root = generateTree(pq) # Print Huffman Codes arr = [ 0 ] * MAX_SIZE top = 0 printCodes(root, arr, top) # Driver Code if __name__ = = '__main__' : data = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ] freq = [ 5 , 9 , 12 , 13 , 16 , 45 ] size = len (data) HuffmanCodes(data, freq, size) |
C#
using System; using System.Collections.Generic; public class HuffmanTreeNode : IComparable<HuffmanTreeNode> { public char Data { get ; set ; } public int Freq { get ; set ; } public HuffmanTreeNode Left { get ; set ; } public HuffmanTreeNode Right { get ; set ; } public HuffmanTreeNode( char character, int frequency) { Data = character; Freq = frequency; Left = Right = null ; } public int CompareTo(HuffmanTreeNode other) { return Freq - other.Freq; } } public class GFG { // Maximum Height of Huffman Tree. private const int MaxSize = 100; // Function to print the huffman code for each // character. It uses arr to store the codes private static void PrintCodes(HuffmanTreeNode root, int [] arr, int top) { // Assign 0 to the left node and recur if (root.Left != null ) { arr[top] = 0; PrintCodes(root.Left, arr, top + 1); } // Assign 1 to the right node and recur if (root.Right != null ) { arr[top] = 1; PrintCodes(root.Right, arr, top + 1); } // If this is a leaf node, then we print root.Data // We also print the code for this character from // arr if (root.Left == null && root.Right == null ) { Console.Write(root.Data + " " ); for ( int i = 0; i < top; ++i) { Console.Write(arr[i]); } Console.WriteLine(); } } // Function to generate Huffman Encoding Tree private static HuffmanTreeNode GenerateTree(SortedList< int , HuffmanTreeNode> list) { // We keep on looping till only one node remains in // the SortedList while (list.Count != 1) { // Node which has least frequency HuffmanTreeNode left = list.Values[0]; list.RemoveAt(0); // Node which has least frequency HuffmanTreeNode right = list.Values[0]; list.RemoveAt(0); // A new node is formed with frequency left.Freq // + right.Freq We take data as '$' because we // are only concerned with the frequency HuffmanTreeNode node = new HuffmanTreeNode( '$' , left.Freq + right.Freq); node.Left = left; node.Right = right; // Add the new node back to the SortedList list.Add(node.Freq, node); } return list.Values[0]; } // Function to generate Huffman Codes public static void HuffmanCodes( char [] data, int [] freq, int size) { // Declaring SortedList using custom comparer SortedList< int , HuffmanTreeNode> list = new SortedList< int , HuffmanTreeNode>(); // Populating the SortedList for ( int i = 0; i < size; i++) { HuffmanTreeNode newNode = new HuffmanTreeNode(data[i], freq[i]); list.Add(freq[i], newNode); } // Generate Huffman Encoding Tree and get the root // node HuffmanTreeNode root = GenerateTree(list); // Print Huffman Codes int [] arr = new int [MaxSize]; int top = 0; PrintCodes(root, arr, top); } // Driver Code public static void Main( string [] args) { char [] data = { 'a' , 'b' , 'c' , 'd' , 'e' , 'f' }; int [] freq = { 5, 9, 12, 13, 16, 45 }; int size = data.Length; // Function call HuffmanCodes(data, freq, size); } } |
Javascript
// javascript Program for Huffman Coding // using Priority Queue class HuffmanTreeNode { // Initializing the // current node constructor(character, frequency) { // Stores character this .data = character; // Stores frequency of // the character this .freq = frequency; // Left child of the // current node this .left = null ; // Right child of the // current node this .right = null ; } } // Custom comparator class class Compare { constructor() {} static compare(a, b) { // Defining priority on // the basis of frequency return a.freq - b.freq; } } // Function to generate Huffman // Encoding Tree function generateTree(pq) { // We keep on looping till // only one node remains in // the Priority Queue while (pq.length > 1) { // Node which has least // frequency const left = pq.shift(); // Remove node from // Priority Queue const right = pq.shift(); // A new node is formed // with frequency left->freq // + right->freq // We take data as '$' // because we are only // concerned with the // frequency const node = new HuffmanTreeNode( '$' , left.freq + right.freq); node.left = left; node.right = right; // Push back node // created to the // Priority Queue pq.push(node); pq.sort(Compare.compare); } return pq[0]; } // Function to print the // huffman code for each // character. // It uses arr to store the codes function printCodes(root, arr, top) { // Assign 0 to the left node // and recur if (root.left) { arr[top] = 0; printCodes(root.left, arr, top + 1); } // Assign 1 to the right // node and recur if (root.right) { arr[top] = 1; printCodes(root.right, arr, top + 1); } // If this is a leaf node, // then we print root->data // We also print the code // for this character from arr if (!root.left && !root.right) { console.log(root.data + ' ' + arr.slice(0, top).join( '' )); } } function HuffmanCodes(data, freq, size) { // Maximum Height of Huffman Tree. const MAX_SIZE = 100; // Declaring priority queue // using custom comparator const pq = []; // Populating the priority // queue for (let i = 0; i < size; i++) { const newNode = new HuffmanTreeNode(data[i], freq[i]); pq.push(newNode); } pq.sort(Compare.compare); // Generate Huffman Encoding // Tree and get the root node const root = generateTree(pq); const arr = new Array(MAX_SIZE); const top = 0; // Print Huffman Codes printCodes(root, arr, top); } // Driver Code const data = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ]; const freq = [5, 9, 12, 13, 16, 45]; const size = data.length; HuffmanCodes(data, freq, size); // This code is contributed by shiv1o43g |
Output:
f 0 c 100 d 101 a 1100 b 1101 e 111
Time Complexity: O(n*logn) where n is the number of unique characters
Auxiliary Space: O(n)
Please Login to comment...