Huffman Coding using Priority Queue
Last Updated :
20 Mar, 2023
Improve
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++ 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;
}
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);
}
}
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)
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 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)