(Translated by https://www.hiragana.jp/)
Efficient Huffman Coding for Sorted Input | Greedy Algo-4 - GeeksforGeeks
Open In App

Efficient Huffman Coding for Sorted Input | Greedy Algo-4

Last Updated : 06 Nov, 2023
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Save
Share
Report
News Follow

We recommend to read following post as a prerequisite for this.
Greedy Algorithms | Set 3 (Huffman Coding)

Time complexity of the algorithm discussed in above post is O(nLogn). If we know that the given array is sorted (by non-decreasing order of frequency), we can generate Huffman codes in O(n) time. Following is a O(n) algorithm for sorted input.
1. Create two empty queues.
2. Create a leaf node for each unique character and Enqueue it to the first queue in non-decreasing order of frequency. Initially second queue is empty.
3. Dequeue two nodes with the minimum frequency by examining the front of both queues. Repeat the following steps two times 
        1. If second queue is empty, dequeue from first queue. 
        2. If first queue is empty, dequeue from second queue. 
        3. Else, compare the front of two queues and dequeue the minimum. 
4. Create a new internal node with frequency equal to the sum of the two nodes frequencies. Make the first Dequeued node as its left child and the second Dequeued node as right child. Enqueue this node to second queue.
5. Repeat steps#3 and #4 while there is more than one node in the queues. The remaining node is the root node and the tree is complete. 

C++14




// Clean c++ stl code to generate huffman codes if the array
// is sorted in non-decreasing order
#include <bits/stdc++.h>
using namespace std;
 
// Node structure for creating a binary tree
struct Node {
    char ch;
    int freq;
    Node* left;
    Node* right;
    Node(char c, int f, Node* l = nullptr,
         Node* r = nullptr)
        : ch(c)
        , freq(f)
        , left(l)
        , right(r){};
};
 
// Find the min freq node between q1 and q2
Node* minNode(queue<Node*>& q1, queue<Node*>& q2)
{
    Node* temp;
 
    if (q1.empty()) {
        temp = q2.front();
        q2.pop();
        return temp;
    }
 
    if (q2.empty()) {
        temp = q1.front();
        q1.pop();
        return temp;
    }
 
    if (q1.front()->freq < q2.front()->freq) {
        temp = q1.front();
        q1.pop();
        return temp;
    }
    else {
        temp = q2.front();
        q2.pop();
        return temp;
    }
}
 
// Function to print the generated huffman codes
void printHuffmanCodes(Node* root, string str = "")
{
    if (!root)
        return;
    if (root->ch != '$') {
        cout << root->ch << ": " << str << '\n';
        return;
    }
 
    printHuffmanCodes(root->left, str + "0");
    printHuffmanCodes(root->right, str + "1");
 
    return;
}
 
// Function to generate huffman codes
void generateHuffmanCode(vector<pair<char, int> > v)
{
    if (!v.size())
        return;
 
    queue<Node*> q1;
    queue<Node*> q2;
 
    for (auto it = v.begin(); it != v.end(); ++it)
        q1.push(new Node(it->first, it->second));
 
    while (!q1.empty() or q2.size() > 1) {
        Node* l = minNode(q1, q2);
        Node* r = minNode(q1, q2);
        Node* node = new Node('$', l->freq + r->freq, l, r);
        q2.push(node);
    }
 
    printHuffmanCodes(q2.front());
    return;
}
 
int main()
{
    vector<pair<char, int> > v
        = { { 'a' , 5 },  { 'b' , 9 },  { 'c' , 12 },
            { 'd' , 13 }, { 'e' , 16 }, { 'f' , 45 } };
    generateHuffmanCode(v);
    return 0;
}


C++




// C++ Program for Efficient Huffman Coding for Sorted input
#include <bits/stdc++.h>
using namespace std;
 
// This constant can be avoided by explicitly
// calculating height of Huffman Tree
#define MAX_TREE_HT 100
 
// A node of huffman tree
class QueueNode {
public:
    char data;
    unsigned freq;
    QueueNode *left, *right;
};
 
// Structure for Queue: collection
// of Huffman Tree nodes (or QueueNodes)
class Queue {
public:
    int front, rear;
    int capacity;
    QueueNode** array;
};
 
// A utility function to create a new Queuenode
QueueNode* newNode(char data, unsigned freq)
{
    QueueNode* temp = new QueueNode[(sizeof(QueueNode))];
    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;
    return temp;
}
 
// A utility function to create a Queue of given capacity
Queue* createQueue(int capacity)
{
    Queue* queue = new Queue[(sizeof(Queue))];
    queue->front = queue->rear = -1;
    queue->capacity = capacity;
    queue->array = new QueueNode*[(queue->capacity
                                   * sizeof(QueueNode*))];
    return queue;
}
 
// A utility function to check if size of given queue is 1
int isSizeOne(Queue* queue)
{
    return queue->front == queue->rear
           && queue->front != -1;
}
 
// A utility function to check if given queue is empty
int isEmpty(Queue* queue) { return queue->front == -1; }
 
// A utility function to check if given queue is full
int isFull(Queue* queue)
{
    return queue->rear == queue->capacity - 1;
}
 
// A utility function to add an item to queue
void enQueue(Queue* queue, QueueNode* item)
{
    if (isFull(queue))
        return;
    queue->array[++queue->rear] = item;
    if (queue->front == -1)
        ++queue->front;
}
 
// A utility function to remove an item from queue
QueueNode* deQueue(Queue* queue)
{
    if (isEmpty(queue))
        return NULL;
    QueueNode* temp = queue->array[queue->front];
    if (queue->front
        == queue
               ->rear) // If there is only one item in queue
        queue->front = queue->rear = -1;
    else
        ++queue->front;
    return temp;
}
 
// A utility function to get form of queue
QueueNode* getFront(Queue* queue)
{
    if (isEmpty(queue))
        return NULL;
    return queue->array[queue->front];
}
 
/* A function to get minimum item from two queues */
QueueNode* findMin(Queue* firstQueue, Queue* secondQueue)
{
    // Step 3.a: If first queue is empty, dequeue from
    // second queue
    if (isEmpty(firstQueue))
        return deQueue(secondQueue);
 
    // Step 3.b: If second queue is empty, dequeue from
    // first queue
    if (isEmpty(secondQueue))
        return deQueue(firstQueue);
 
    // Step 3.c: Else, compare the front of two queues and
    // dequeue minimum
    if (getFront(firstQueue)->freq
        < getFront(secondQueue)->freq)
        return deQueue(firstQueue);
 
    return deQueue(secondQueue);
}
 
// Utility function to check if this node is leaf
int isLeaf(QueueNode* root)
{
    return !(root->left) && !(root->right);
}
 
// A utility function to print an array of size n
void printArr(int arr[], int n)
{
    int i;
    for (i = 0; i < n; ++i)
        cout << arr[i];
    cout << endl;
}
 
// The main function that builds Huffman tree
QueueNode* buildHuffmanTree(char data[], int freq[],
                            int size)
{
    QueueNode *left, *right, *top;
 
    // Step 1: Create two empty queues
    Queue* firstQueue = createQueue(size);
    Queue* secondQueue = createQueue(size);
 
    // Step 2:Create a leaf node for each unique character
    // and Enqueue it to the first queue in non-decreasing
    // order of frequency. Initially second queue is empty
    for (int i = 0; i < size; ++i)
        enQueue(firstQueue, newNode(data[i], freq[i]));
 
    // Run while Queues contain more than one node. Finally,
    // first queue will be empty and second queue will
    // contain only one node
    while (
        !(isEmpty(firstQueue) && isSizeOne(secondQueue))) {
        // Step 3: Dequeue two nodes with the minimum
        // frequency by examining the front of both queues
        left = findMin(firstQueue, secondQueue);
        right = findMin(firstQueue, secondQueue);
 
        // Step 4: Create a new internal node with frequency
        // equal to the sum of the two nodes frequencies.
        // Enqueue this node to second queue.
        top = newNode('$', left->freq + right->freq);
        top->left = left;
        top->right = right;
        enQueue(secondQueue, top);
    }
 
    return deQueue(secondQueue);
}
 
// Prints huffman codes from the root of Huffman Tree. It
// uses arr[] to store codes
void printCodes(QueueNode* root, int arr[], int top)
{
    // Assign 0 to left edge and recur
    if (root->left) {
        arr[top] = 0;
        printCodes(root->left, arr, top + 1);
    }
 
    // Assign 1 to right edge and recur
    if (root->right) {
        arr[top] = 1;
        printCodes(root->right, arr, top + 1);
    }
 
    // If this is a leaf node, then it contains one of the
    // input characters, print the character and its code
    // from arr[]
    if (isLeaf(root)) {
        cout << root->data << ": ";
        printArr(arr, top);
    }
}
 
// The main function that builds a Huffman Tree and print
// codes by traversing the built Huffman Tree
void HuffmanCodes(char data[], int freq[], int size)
{
    // Construct Huffman Tree
    QueueNode* root = buildHuffmanTree(data, freq, size);
 
    // Print Huffman codes using the Huffman tree built
    // above
    int arr[MAX_TREE_HT], top = 0;
    printCodes(root, arr, top);
}
 
// Driver code
int main()
{
    char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
    int freq[] = { 5, 9, 12, 13, 16, 45 };
    int size = sizeof(arr) / sizeof(arr[0]);
    HuffmanCodes(arr, freq, size);
    return 0;
}
 
// This code is contributed by rathbhupendra


C




// C Program for Efficient Huffman Coding for Sorted input
#include <stdio.h>
#include <stdlib.h>
 
// This constant can be avoided by explicitly calculating
// height of Huffman Tree
#define MAX_TREE_HT 100
 
// A node of huffman tree
struct QueueNode {
    char data;
    unsigned freq;
    struct QueueNode *left, *right;
};
 
// Structure for Queue: collection of Huffman Tree nodes (or
// QueueNodes)
struct Queue {
    int front, rear;
    int capacity;
    struct QueueNode** array;
};
 
// A utility function to create a new Queuenode
struct QueueNode* newNode(char data, unsigned freq)
{
    struct QueueNode* temp = (struct QueueNode*)malloc(
        sizeof(struct QueueNode));
    temp->left = temp->right = NULL;
    temp->data = data;
    temp->freq = freq;
    return temp;
}
 
// A utility function to create a Queue of given capacity
struct Queue* createQueue(int capacity)
{
    struct Queue* queue
        = (struct Queue*)malloc(sizeof(struct Queue));
    queue->front = queue->rear = -1;
    queue->capacity = capacity;
    queue->array = (struct QueueNode**)malloc(
        queue->capacity * sizeof(struct QueueNode*));
    return queue;
}
 
// A utility function to check if size of given queue is 1
int isSizeOne(struct Queue* queue)
{
    return queue->front == queue->rear
           && queue->front != -1;
}
 
// A utility function to check if given queue is empty
int isEmpty(struct Queue* queue)
{
    return queue->front == -1;
}
 
// A utility function to check if given queue is full
int isFull(struct Queue* queue)
{
    return queue->rear == queue->capacity - 1;
}
 
// A utility function to add an item to queue
void enQueue(struct Queue* queue, struct QueueNode* item)
{
    if (isFull(queue))
        return;
    queue->array[++queue->rear] = item;
    if (queue->front == -1)
        ++queue->front;
}
 
// A utility function to remove an item from queue
struct QueueNode* deQueue(struct Queue* queue)
{
    if (isEmpty(queue))
        return NULL;
    struct QueueNode* temp = queue->array[queue->front];
    if (queue->front
        == queue
               ->rear) // If there is only one item in queue
        queue->front = queue->rear = -1;
    else
        ++queue->front;
    return temp;
}
 
// A utility function to get form of queue
struct QueueNode* getFront(struct Queue* queue)
{
    if (isEmpty(queue))
        return NULL;
    return queue->array[queue->front];
}
 
/* A function to get minimum item from two queues */
struct QueueNode* findMin(struct Queue* firstQueue,
                          struct Queue* secondQueue)
{
    // Step 3.a: If first queue is empty, dequeue from
    // second queue
    if (isEmpty(firstQueue))
        return deQueue(secondQueue);
 
    // Step 3.b: If second queue is empty, dequeue from
    // first queue
    if (isEmpty(secondQueue))
        return deQueue(firstQueue);
 
    // Step 3.c:  Else, compare the front of two queues and
    // dequeue minimum
    if (getFront(firstQueue)->freq
        < getFront(secondQueue)->freq)
        return deQueue(firstQueue);
 
    return deQueue(secondQueue);
}
 
// Utility function to check if this node is leaf
int isLeaf(struct QueueNode* root)
{
    return !(root->left) && !(root->right);
}
 
// A utility function to print an array of size n
void printArr(int arr[], int n)
{
    int i;
    for (i = 0; i < n; ++i)
        printf("%d", arr[i]);
    printf("\n");
}
 
// The main function that builds Huffman tree
struct QueueNode* buildHuffmanTree(char data[], int freq[],
                                   int size)
{
    struct QueueNode *left, *right, *top;
 
    // Step 1: Create two empty queues
    struct Queue* firstQueue = createQueue(size);
    struct Queue* secondQueue = createQueue(size);
 
    // Step 2:Create a leaf node for each unique character
    // and Enqueue it to the first queue in non-decreasing
    // order of frequency. Initially second queue is empty
    for (int i = 0; i < size; ++i)
        enQueue(firstQueue, newNode(data[i], freq[i]));
 
    // Run while Queues contain more than one node. Finally,
    // first queue will be empty and second queue will
    // contain only one node
    while (
        !(isEmpty(firstQueue) && isSizeOne(secondQueue))) {
        // Step 3: Dequeue two nodes with the minimum
        // frequency by examining the front of both queues
        left = findMin(firstQueue, secondQueue);
        right = findMin(firstQueue, secondQueue);
 
        // Step 4: Create a new internal node with frequency
        // equal to the sum of the two nodes frequencies.
        // Enqueue this node to second queue.
        top = newNode('$', left->freq + right->freq);
        top->left = left;
        top->right = right;
        enQueue(secondQueue, top);
    }
 
    return deQueue(secondQueue);
}
 
// Prints huffman codes from the root of Huffman Tree.  It
// uses arr[] to store codes
void printCodes(struct QueueNode* root, int arr[], int top)
{
    // Assign 0 to left edge and recur
    if (root->left) {
        arr[top] = 0;
        printCodes(root->left, arr, top + 1);
    }
 
    // Assign 1 to right edge and recur
    if (root->right) {
        arr[top] = 1;
        printCodes(root->right, arr, top + 1);
    }
 
    // If this is a leaf node, then it contains one of the
    // input characters, print the character and its code
    // from arr[]
    if (isLeaf(root)) {
        printf("%c: ", root->data);
        printArr(arr, top);
    }
}
 
// The main function that builds a Huffman Tree and print
// codes by traversing the built Huffman Tree
void HuffmanCodes(char data[], int freq[], int size)
{
    //  Construct Huffman Tree
    struct QueueNode* root
        = buildHuffmanTree(data, freq, size);
 
    // Print Huffman codes using the Huffman tree built
    // above
    int arr[MAX_TREE_HT], top = 0;
    printCodes(root, arr, top);
}
 
// Driver program to test above functions
int main()
{
    char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
    int freq[] = { 5, 9, 12, 13, 16, 45 };
    int size = sizeof(arr) / sizeof(arr[0]);
    HuffmanCodes(arr, freq, size);
    return 0;
}


Java




//// C++ Program for Efficient Huffman Coding for Sorted input //
 
import java.util.PriorityQueue;
import java.util.HashMap;
 
// Node structure for creating a binary tree //
class Node {
    char ch;
    int freq;
    Node left;
    Node right;
 
    Node(char c, int f) {
        ch = c;
        freq = f;
        left = null;
        right = null;
    }
}
 
public class Main {
    // Function to print the generated Huffman codes
    static void printHuffmanCodes(Node root, String str) {
        if (root == null)
            return;
        if (root.ch != '$') {
            System.out.println(root.ch + ": " + str);
            return;
        }
 
        printHuffmanCodes(root.left, str + "0");
        printHuffmanCodes(root.right, str + "1");
    }
 
    // Function to generate Huffman codes
    static void generateHuffmanCode(HashMap<Character, Integer> charFreq) {
        if (charFreq.isEmpty())
            return;
 
        PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> a.freq - b.freq);
 
        for (char c : charFreq.keySet()) {
            pq.add(new Node(c, charFreq.get(c)));
        }
 
        while (pq.size() > 1) {
            Node left = pq.poll();
            Node right = pq.poll();
            Node node = new Node('$', left.freq + right.freq);
            node.left = left;
            node.right = right;
            pq.add(node);
        }
 
        printHuffmanCodes(pq.poll(), "");
    }
 
    public static void main(String[] args) {
        HashMap<Character, Integer> charFreq = new HashMap<>();
        charFreq.put('a', 5);
        charFreq.put('b', 9);
        charFreq.put('c', 12);
        charFreq.put('d', 13);
        charFreq.put('e', 16);
        charFreq.put('f', 45);
 
        generateHuffmanCode(charFreq);
    }
}


Python3




# Python3 program for Efficient Huffman Coding
# for Sorted input
 
# Class for the nodes of the Huffman tree
class QueueNode:
     
    def __init__(self, data = None, freq = None,
                 left = None, right = None):
        self.data = data
        self.freq = freq
        self.left = left
        self.right = right
 
    # Function to check if the following
    # node is a leaf node
    def isLeaf(self):
        return (self.left == None and
                self.right == None)
 
# Class for the two Queues
class Queue:
     
    def __init__(self):
        self.queue = []
 
    # Function for checking if the
    # queue has only 1 node
    def isSizeOne(self):
        return len(self.queue) == 1
 
    # Function for checking if
    # the queue is empty
    def isEmpty(self):
        return self.queue == []
 
    # Function to add item to the queue
    def enqueue(self, x):
        self.queue.append(x)
 
    # Function to remove item from the queue
    def dequeue(self):
        return self.queue.pop(0)
 
# Function to get minimum item from two queues
def findMin(firstQueue, secondQueue):
     
    # Step 3.1: If second queue is empty,
    # dequeue from first queue
    if secondQueue.isEmpty():
        return firstQueue.dequeue()
 
    # Step 3.2: If first queue is empty,
    # dequeue from second queue
    if firstQueue.isEmpty():
        return secondQueue.dequeue()
 
    # Step 3.3:  Else, compare the front of
    # two queues and dequeue minimum
    if (firstQueue.queue[0].freq <
        secondQueue.queue[0].freq):
        return firstQueue.dequeue()
 
    return secondQueue.dequeue()
 
# The main function that builds Huffman tree
def buildHuffmanTree(data, freq, size):
     
    # Step 1: Create two empty queues
    firstQueue = Queue()
    secondQueue = Queue()
 
    # Step 2: Create a leaf node for each unique
    # character and Enqueue it to the first queue
    # in non-decreasing order of frequency.
    # Initially second queue is empty.
    for i in range(size):
        firstQueue.enqueue(QueueNode(data[i], freq[i]))
 
    # Run while Queues contain more than one node.
    # Finally, first queue will be empty and
    # second queue will contain only one node
    while not (firstQueue.isEmpty() and
               secondQueue.isSizeOne()):
                    
        # Step 3: Dequeue two nodes with the minimum
        # frequency by examining the front of both queues
        left = findMin(firstQueue, secondQueue)
        right = findMin(firstQueue, secondQueue)
 
        # Step 4: Create a new internal node with
        # frequency equal to the sum of the two
        # nodes frequencies. Enqueue this node
        # to second queue.
        top = QueueNode("$", left.freq + right.freq,
                        left, right)
        secondQueue.enqueue(top)
 
    return secondQueue.dequeue()
 
# Prints huffman codes from the root of
# Huffman tree. It uses arr[] to store codes
def printCodes(root, arr):
     
    # Assign 0 to left edge and recur
    if root.left:
        arr.append(0)
        printCodes(root.left, arr)
        arr.pop(-1)
 
    # Assign 1 to right edge and recur
    if root.right:
        arr.append(1)
        printCodes(root.right, arr)
        arr.pop(-1)
 
    # If this is a leaf node, then it contains
    # one of the input characters, print the
    # character and its code from arr[]
    if root.isLeaf():
        print(f"{root.data}: ", end = "")
        for i in arr:
            print(i, end = "")
             
        print()
 
# The main function that builds a Huffman
# tree and print codes by traversing the
# built Huffman tree
def HuffmanCodes(data, freq, size):
     
    # Construct Huffman Tree
    root = buildHuffmanTree(data, freq, size)
 
    # Print Huffman codes using the Huffman
    # tree built above
    arr = []
    printCodes(root, arr)
 
# Driver code
arr = ["a", "b", "c", "d", "e", "f"]
freq = [5, 9, 12, 13, 16, 45]
size = len(arr)
 
HuffmanCodes(arr, freq, size)
 
# This code is contributed by Kevin Joshi


C#




// Clean c++ stl code to generate huffman codes if the array
// is sorted in non-decreasing order
 
using System;
using System.Collections.Generic;
 
// Node structure for creating a binary tree
public class Node {
    public char Ch
    {
        get;
        set;
    }
    public int Freq
    {
        get;
        set;
    }
    public Node Left
    {
        get;
        set;
    }
    public Node Right
    {
        get;
        set;
    }
 
    public Node(char c, int f, Node l = null, Node r = null)
    {
        Ch = c;
        Freq = f;
        Left = l;
        Right = r;
    }
}
 
class Program {
    // Find the min freq node between q1 and q2
    static Node MinNode(Queue<Node> q1, Queue<Node> q2)
    {
        Node temp;
 
        if (q1.Count == 0) {
            temp = q2.Dequeue();
            return temp;
        }
 
        if (q2.Count == 0) {
            temp = q1.Dequeue();
            return temp;
        }
 
        if (q1.Peek().Freq < q2.Peek().Freq) {
            temp = q1.Dequeue();
            return temp;
        }
        else {
            temp = q2.Dequeue();
            return temp;
        }
    }
 
    // Function to print the generated huffman codes
    static void PrintHuffmanCodes(Node root,
                                  string str = "")
    {
        if (root == null)
            return;
        if (root.Ch != '$') {
            Console.WriteLine(root.Ch + ": " + str);
            return;
        }
 
        PrintHuffmanCodes(root.Left, str + "0");
        PrintHuffmanCodes(root.Right, str + "1");
    }
 
    // Function to generate huffman codes
    static void
    GenerateHuffmanCode(List<Tuple<char, int> > v)
    {
        if (v.Count == 0)
            return;
 
        Queue<Node> q1 = new Queue<Node>();
        Queue<Node> q2 = new Queue<Node>();
 
        foreach(var tuple in v)
        {
            q1.Enqueue(new Node(tuple.Item1, tuple.Item2));
        }
 
        while (q1.Count > 0 || q2.Count > 1) {
            Node l = MinNode(q1, q2);
            Node r = MinNode(q1, q2);
            Node node
                = new Node('$', l.Freq + r.Freq, l, r);
            q2.Enqueue(node);
        }
 
        PrintHuffmanCodes(q2.Peek());
    }
 
    static void Main(string[] args)
    {
        List<Tuple<char, int> > v
            = new List<Tuple<char, int> >{
                  Tuple.Create('a', 5),
                  Tuple.Create('b', 9),
                  Tuple.Create('c', 12),
                  Tuple.Create('d', 13),
                  Tuple.Create('e', 16),
                  Tuple.Create('f', 45)
              };
 
        GenerateHuffmanCode(v);
    }
}


Javascript




// JavaScript program for the above approach
 
// Class for the nodes of the Huffman tree
class QueueNode {
  constructor(data = null, freq = null, left = null, right = null) {
    this.data = data;
    this.freq = freq;
    this.left = left;
    this.right = right;
  }
     
    // Function to check if the following
    // node is a leaf node
  isLeaf() {
    return (this.left == null && this.right == null);
  }
}
 
// Class for the two Queues
class Queue {
  constructor() {
    this.queue = [];
  }
 
   // Function for checking if the
   // queue has only 1 node
  isSizeOne() {
    return this.queue.length == 1;
  }
     
     
   // Function for checking if
   // the queue is empty
  isEmpty() {
    return this.queue.length == 0;
  }
 
  // Function to add item to the queue
  enqueue(x) {
    this.queue.push(x);
  }
 
   // Function to remove item from the queue
  dequeue() {
    return this.queue.shift();
  }
}
 
// Function to get minimum item from two queues
function findMin(firstQueue, secondQueue) {
     
    // Step 3.1: If second queue is empty,
   // dequeue from first queue
  if (secondQueue.isEmpty()) {
    return firstQueue.dequeue();
  }
 
   // Step 3.2: If first queue is empty,
  // dequeue from second queue
  if (firstQueue.isEmpty()) {
    return secondQueue.dequeue();
  }
 
    // Step 3.3:  Else, compare the front of
   // two queues and dequeue minimum
  if (firstQueue.queue[0].freq < secondQueue.queue[0].freq) {
    return firstQueue.dequeue();
  }
 
  return secondQueue.dequeue();
}
 
// The main function that builds Huffman tree
function buildHuffmanTree(data, freq, size) {
  // Step 1: Create two empty queues
  let firstQueue = new Queue();
  let secondQueue = new Queue();
 
 
     
   // Step 2: Create a leaf node for each unique
   // character and Enqueue it to the first queue
   // in non-decreasing order of frequency.
   // Initially second queue is empty.
  for (let i = 0; i < size; i++) {
    firstQueue.enqueue(new QueueNode(data[i], freq[i]));
  }
 
     
  // Run while Queues contain more than one node.
  // Finally, first queue will be empty and
  // second queue will contain only one node
  while (!(firstQueue.isEmpty() && secondQueue.isSizeOne())) {
                          
    // Step 3: Dequeue two nodes with the minimum
    // frequency by examining the front of both queues
    let left = findMin(firstQueue, secondQueue);
    let right = findMin(firstQueue, secondQueue);
     
    // Step 4: Create a new internal node with
    // frequency equal to the sum of the two
    // nodes frequencies. Enqueue this node
    // to second queue.
    let top = new QueueNode("$", left.freq + right.freq, left, right);
    secondQueue.enqueue(top);
  }
 
  return secondQueue.dequeue();
}
 
 
// Prints huffman codes from the root of
// Huffman tree. It uses arr[] to store codes
function printCodes(root, arr) {
   
  // Assign 0 to left edge and recur
  if (root.left) {
    arr.push(0);
    printCodes(root.left, arr);
    arr.pop();
  }
     
  // Assign 1 to right edge and recur
  if (root.right) {
    arr.push(1);
    printCodes(root.right, arr);
    arr.pop();
  }
 
   // If this is a leaf node, then it contains
  // one of the input characters, print the
  // character and its code from arr[]
  if (root.isLeaf()) {
    let output = root.data + ": ";
    for (let i = 0; i < arr.length; i++) {
      output += arr[i];
    }
    console.log(output);
  }
}
 
// The main function that builds a Huffman
// tree and print codes by traversing the
// built Huffman tree
function HuffmanCodes(data, freq, size) {
     
  // Construct Huffman Tree
  let root = buildHuffmanTree(data, freq, size);
   
   
  // Print Huffman codes using the Huffman
  // tree built above
  let arr = [];
  printCodes(root, arr);
}
 
// Driver code
let arr = ["a", "b", "c", "d", "e", "f"];
let freq = [5, 9, 12, 13, 16, 45];
let size = arr.length;
HuffmanCodes(arr, freq, size);
 
// This code is contributed by Prince Kumar


Output: 

f: 0
c: 100
d: 101
a: 1100
b: 1101
e: 111

Time complexity: O(n)
If the input is not sorted, it needs to be sorted first before it can be processed by the above algorithm. Sorting can be done using heap sort or merge-sort both of which run in Theta(nlogn). So, the overall time complexity becomes O(nlogn) for unsorted input. 
Auxiliary Space: O(n)

Reference: 
http://en.wikipedia.org/wiki/Huffman_coding
This article is compiled by Aashish Barnwal and reviewed by GeeksforGeeks team.  



Previous Article
Next Article

Similar Reads

Huffman Coding | Greedy Algo-3
Huffman coding is a lossless data compression algorithm. The idea is to assign variable-length codes to input characters, lengths of the assigned codes are based on the frequencies of corresponding characters. The variable-length codes assigned to input characters are Prefix Codes, means the codes (bit sequences) are assigned in such a way that the
15+ min read
Boruvka's algorithm | Greedy Algo-9
We have discussed the following topics on Minimum Spanning Tree.Applications of Minimum Spanning Tree Problem Kruskal’s Minimum Spanning Tree Algorithm Prim’s Minimum Spanning Tree AlgorithmIn this post, Boruvka's algorithm is discussed. Like Prim's and Kruskal's, Boruvka’s algorithm is also a Greedy algorithm. Below is a complete algorithm. 1) Inp
15+ min read
Prim’s MST for Adjacency List Representation | Greedy Algo-6
We recommend reading the following two posts as a prerequisite to this post. Greedy Algorithms | Set 5 (Prim’s Minimum Spanning Tree (MST)) Graph and its representationsWe have discussed Prim's algorithm and its implementation for adjacency matrix representation of graphs. The time complexity for the matrix representation is O(V^2). In this post, O
15+ min read
Dijkstra’s Algorithm for Adjacency List Representation | Greedy Algo-8
We recommend reading the following two posts as a prerequisite for this post. Greedy Algorithms | Set 7 (Dijkstra’s shortest path algorithm) Graph and its representations We have discussed Dijkstra's algorithm and its implementation for adjacency matrix representation of graphs. The time complexity for the matrix representation is O(V^2). In this p
15+ min read
Activity Selection Problem | Greedy Algo-1
Greedy is an algorithmic paradigm that builds up a solution piece by piece, always choosing the next piece that offers the most obvious and immediate benefit. Greedy algorithms are used for optimization problems. An optimization problem can be solved using Greedy if the problem has the following property: At every step, we can make a choice that lo
15+ min read
Adaptive Huffman Coding And Decoding
Prerequisite: Huffman Coding, Huffman Decoding Adaptive Huffman Coding is also known as Dynamic Huffman Coding. The implementation is done using Vitter Algorithm. Encoding Adaptive Huffman coding for a string containing alphabets: Let m be the total number of alphabets. So m = 26. For Vitter Algorithm, find a parameters e & r such that m = 2e +
7 min read
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,
12 min read
Time and Space Complexity of Huffman Coding Algorithm
Huffman coding is a popular algorithm used for the lossless data compression. It works by assigning variable-length codes to input characters with the shorter codes assigned to more frequent characters. This results in a prefix-free binary code meaning no code is a prefix of the another. The algorithm was developed by the David A. Huffman in 1952 a
2 min read
Huffman Coding in Python
Huffman Coding is one of the most popular lossless data compression techniques. This article aims at diving deep into the Huffman Coding and its implementation in Python. What is Huffman Coding?Huffman Coding is an approach used in lossless data compression with the primary objective of delivering reduced transit size without any loss of meaningful
3 min read
Text File Compression And Decompression Using Huffman Coding
Text files can be compressed to make them smaller and faster to send, and unzipping files on devices has a low overhead. The process of encoding involves changing the representation of a file so that the (binary) compressed output takes less space to store and takes less time to transmit while retaining the ability to reconstruct the original file
14 min read
Practice Questions on Huffman Encoding
Huffman Encoding is an important topic from GATE point of view and different types of questions are asked from this topic. Before understanding this article, you should have basic idea about Huffman encoding. These are the types of questions asked in GATE based on Huffman Encoding. Type 1. Conceptual questions based on Huffman Encoding - Here are t
4 min read
Huffman Decoding
We have discussed Huffman Encoding in a previous post. In this post, decoding is discussed. Examples: Input Data: AAAAAABCCCCCCDDEEEEEFrequencies: A: 6, B: 1, C: 6, D: 2, E: 5 Encoded Data: 0000000000001100101010101011111111010101010 Huffman Tree: '#' is the special character usedfor internal nodes as character field is not needed for internal node
15 min read
What coding habits improve timing in coding contest?
It is fun and fruitful to participate in coding challenges and hackathons offline or online. There are lots of prices and incentives that you can win in these contests. You can showcase your skill and get awarded for it. Hackathons are generally held for 1 to 7 days or a fixed period of time, similar for coding challenges. The one thing that you mu
4 min read
Geeks Coding Challenge [GCC 2019] - A Three Day Coding Challenge By GeeksforGeeks
Remember the memories of your childhood when you accepted the challenge to solve some Jigsaw Puzzle, Complex Mathematics Problems, Tic-Tac-Toe, Sudoku or Rubik's cube kinda brain teaser game. Maybe it was scary the first time but when you solved the problem it was exciting, fun, challenging and interesting for you. Whether it's a game or it's real-
7 min read
Top 10 Coding Platforms to Enhance Your Coding Skills in 2024
Everyone wants to be among the best, but what does it take to become an exceptional coder? Just like a racer needs to train rigorously to win races, a programmer must consistently practice and refine their skills. The best way to do this is through hands-on coding experience, and that’s where coding practice platforms come into play. These platform
9 min read
Mo's Algo with update and without update
Mo's Algorithm is a truly versatile algorithm that finds utility in a vast array of problems requiring querying an array or a list for a subarray. Now, let me tell you, this algorithm owes its efficiency to a very specific order of processing the queries, which significantly reduces the time required to access the array elements. How does Mo's Algo
15+ min read
Coin game of two corners (Greedy Approach)
Consider a two-player coin game where each player gets turned one by one. There is a row of even a number of coins, and a player on his/her turn can pick a coin from any of the two corners of the row. The player that collects coins with more value wins the game. Develop a strategy for the player making the first turn, such that he/she never loses t
9 min read
What is Greedy Algorithm in DSA?
A Greedy Algorithm is defined as a problem-solving strategy that makes the locally optimal choice at each step of the algorithm, with the hope that this will lead to a globally optimal solution. In other words, a greedy algorithm always chooses the option that seems the best at the moment, without considering the future consequences or possibilitie
4 min read
Minimum number of subsequences required to convert one string to another using Greedy Algorithm
Given two strings A and B consists of lowercase letters, the task to find the minimum number of subsequence required to form A from B. If it is impossible to form, print -1.Examples: Input: A = "aacbe", B = "aceab" Output: 3 Explanation: The minimum number of subsequences required for creating A from B is "aa", "cb" and "e".Input: A = "geeks", B =
13 min read
Maximum profit by buying and selling a share at most K times | Greedy Approach
In share trading, a buyer buys shares and sells on a future date. Given the stock price of N days, the trader is allowed to make at most K transactions, where a new transaction can only start after the previous transaction is complete. The task is to find out the maximum profit that a share trader could have made. Examples: Input: prices[] = {10, 2
11 min read
Greedy Algorithms (General Structure and Applications)
The general structure of a greedy algorithm can be summarized in the following steps:Identify the problem as an optimization problem where we need to find the best solution among a set of possible solutions.Determine the set of feasible solutions for the problem.Identify the optimal substructure of the problem, meaning that the optimal solution to
9 min read
Scheduling in Greedy Algorithms
In this article, we will discuss various scheduling algorithms for Greedy Algorithms. Many scheduling problems can be solved using greedy algorithms. Problem statement: Given N events with their starting and ending times, find a schedule that includes as many events as possible. It is not possible to select an event partially. Consider the below ev
2 min read
Difference between Greedy Algorithm and Divide and Conquer Algorithm
Greedy algorithm and divide and conquer algorithm are two common algorithmic paradigms used to solve problems. The main difference between them lies in their approach to solving problems. Greedy Algorithm:The greedy algorithm is an algorithmic paradigm that follows the problem-solving heuristic of making the locally optimal choice at each stage wit
3 min read
Comparison among Greedy, Divide and Conquer and Dynamic Programming algorithm
Greedy algorithm, divide and conquer algorithm, and dynamic programming algorithm are three common algorithmic paradigms used to solve problems. Here's a comparison among these algorithms: Approach:Greedy algorithm: Makes locally optimal choices at each step with the hope of finding a global optimum.Divide and conquer algorithm: Breaks down a probl
4 min read
Graph Coloring Using Greedy Algorithm
We introduced graph coloring and applications in previous post. As discussed in the previous post, graph coloring is widely used. Unfortunately, there is no efficient algorithm available for coloring a graph with minimum number of colors as the problem is a known NP Complete problem. There are approximate algorithms to solve the problem though. Fol
12 min read
Greedy Algorithm for Egyptian Fraction
Every positive fraction can be represented as sum of unique unit fractions. A fraction is unit fraction if numerator is 1 and denominator is a positive integer, for example 1/3 is a unit fraction. Such a representation is called Egyptian Fraction as it was used by ancient Egyptians. Following are a few examples: Egyptian Fraction Representation of
11 min read
Greedy Approximate Algorithm for Set Cover Problem
Given a universe U of n elements, a collection of subsets of U say S = {S1, S2...,Sm} where every subset Si has an associated cost. Find a minimum cost subcollection of S that covers all elements of U. Example: U = {1,2,3,4,5} S = {S1,S2,S3} S1 = {4,1,3}, Cost(S1) = 5 S2 = {2,5}, Cost(S2) = 10 S3 = {1,4,3,2}, Cost(S3) = 3 Output: Minimum cost of se
6 min read
Greedy Algorithm to find Minimum number of Coins
Given a value of V Rs and an infinite supply of each of the denominations {1, 2, 5, 10, 20, 50, 100, 500, 1000} valued coins/notes, The task is to find the minimum number of coins and/or notes needed to make the change? Examples: Input: V = 70Output: 2Explanation: We need a 50 Rs note and a 20 Rs note. Input: V = 121Output: 3Explanation: We need a
12 min read
Correctness of Greedy Algorithms
A greedy algorithm selects a candidate greedily (local optimum) and adds it to the current solution provided that it doesn't corrupt the feasibility. If the solution obtained by above step is not final, repeat till global optimum or the final solution is obtained. Although there are several mathematical strategies available to proof the correctness
2 min read
Greedy Best first search algorithm
What is the Greedy-Best-first search algorithm?Greedy Best-First Search is an AI search algorithm that attempts to find the most promising path from a given starting point to a goal. It prioritizes paths that appear to be the most promising, regardless of whether or not they are actually the shortest path. The algorithm works by evaluating the cost
5 min read
Practice Tags :