Open In App

Huffman Coding using Priority Queue

Last Updated : 20 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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: 

  1. Push all the characters in ch[] mapped to corresponding frequency freq[] in priority queue.
  2. To create Huffman Tree, pop two nodes from priority queue.
  3. Assign two popped node from priority queue as left and right child of new node.
  4. Push the new node formed in priority queue.
  5. Repeat all above steps until size of priority queue becomes 1.
  6. Traverse the Huffman Tree (whose root is the only node left in the priority queue) to store the Huffman Code
  7. 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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads