C Programming Data Structures Heapify And Priority Queue Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    9 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of C Programming data structures Heapify and Priority Queue

Heaps in C

A Heap is a specialized tree-based data structure that satisfies the heap property. In a max heap, for any given node i, the value of i is greater than or equal to the values of its children. Conversely, in a min heap, the value of i is less than or equal to those of its children. Heap properties make heaps particularly useful as priority queues, where the maximum (or minimum) element must be efficiently retrieved.

Tree Structure

Heaps are commonly implemented using arrays. In an array-based heap, the parent node i has child nodes at positions 2*i + 1 (left child) and 2*i + 2 (right child), and its parent is at (i-1)/2. This array representation is space-efficient because it avoids the need for pointers and does not require memory overhead for storing node pointers.

Heapify Operation

The Heapify process is used to maintain the heap property. It ensures that a subtree rooted at a given node adheres to the heap property. Depending on the type of heap (max or min), the heapify process adjusts the subtree so that the value of each parent node is greater (or less) than its children.

Implementing Heapify

The heapify operation is typically performed in both upward and downward directions:

  • Upward Heapify: After adding a new element, the heapify process starts from the newly added node and moves upwards, swapping nodes to maintain the heap property.
  • Downward Heapify (sift-down): After removing the root node (or any node from the heap), heapify starts from the root and moves downwards, swapping nodes to restore the heap property.

Below is a simple C function to perform heapify in a max heap:

#include <stdio.h>

// Function to heapify a subtree rooted with node i which is an index in arr[]
void heapify(int arr[], int n, int i) {
    int largest = i;  // Initialize largest as root
    int l = 2*i + 1;  // left = 2*i + 1
    int r = 2*i + 2;  // right = 2*i + 2

    // If left child is larger than root
    if (l < n && arr[l] > arr[largest])
        largest = l;
    // If right child is larger than largest so far
    if (r < n && arr[r] > arr[largest])
        largest = r;
    // If largest is not root
    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;

        // Recursively heapify the affected sub-tree
        heapify(arr, n, largest);
    }
}

Priority Queue using Heaps

A Priority Queue is an abstract data type where elements are associated with priorities and are served based on their priority. A max heap is often used to implement a priority queue where the element with the highest priority (largest value) is served first.

Operations

Common operations on a priority queue include:

  1. Insert: Adds an element to the heap and restores the heap property.
  2. Delete: Removes the element with the highest (or lowest) priority and reheapifies.
  3. Peek: Returns the highest (or lowest) priority element without removing it.
  4. Heapsort: Efficiently sorts elements based on priority.

Implementing a Priority Queue

Here’s how to implement a basic priority queue using a max heap in C:

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement C Programming data structures Heapify and Priority Queue

1. Heapify:

Heapify is the process of converting a binary tree into a heap data structure. This can be useful for implementing heapsort or other heap-related operations.

Types of Heaps:

  • Max Heap: For each node i, the value of the node is greater than or equal to the values of its children.
  • Min Heap: For each node i, the value of the node is less than or equal to the values of its children.

We'll implement max heapify.

Example: Max Heapify

Let's create a function to perform max heapify on a subtree rooted at index i. Assume the binary tree is almost a max heap except possibly for the node indexed i.

#include <stdio.h>

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// Function to heapify the subtree rooted at index i which is an index in arr[].
// n is size of heap
void maxHeapify(int arr[], int n, int i) {
    int largest = i; // Initialize largest as root
    int left = 2 * i + 1; // left = 2*i + 1
    int right = 2 * i + 2; // right = 2*i + 2

    // If left child is larger than root
    if (left < n && arr[left] > arr[largest])
        largest = left;

    // If right child is larger than largest so far
    if (right < n && arr[right] > arr[largest])
        largest = right;

    // If largest is not root
    if (largest != i) {
        swap(&arr[i], &arr[largest]);

        // Recursively heapify the affected sub-tree
        maxHeapify(arr, n, largest);
    }
}

int main() {
    // Define an array and size
    int arr[] = {3, 9, 2, 1, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);

    int i = 1; // Index from where we want to apply max heapify
    printf("Original array: ");
    for(int j=0; j<n; j++) 
        printf("%d ", arr[j]);
        
    maxHeapify(arr, n, i);

    printf("\nArray after heapification: ");
    for(int j=0; j<n; j++) 
        printf("%d ", arr[j]);
    
    return 0;
}

Explanation:

  • maxHeapify function ensures that subtree rooted at index i becomes a max heap.
  • Parameters:
    • arr[]: Array representing the binary tree.
    • n: Number of elements in heap.
    • i: Node index to be "heapified".
  • Steps:
    • Find the largest among root, left child, and right child.
    • Recursively heapify the affected subtree.

2. Priority Queue Using Heap

A priority queue is a special kind of queue in which each element is associated with a priority and dequeued based on the priority (higher priority elements are served before lower priority elements). Using heapify helps us in building this priority queue efficiently.

We'll demonstrate a priority queue using max heap.

Example: Max Priority Queue

Let's implement a priority queue that supports insertion and extraction of the maximum element.

#include <stdio.h>
#include <stdlib.h>

// Function to swap two elements
void swap(int *xp, int *yp) {
    int temp = *xp;
    *xp = *yp;
    *yp = temp;
}

// A utility function to max heapify a subtree rooted with node i which is an index in arr[]
void maxHeapify(int arr[], int n, int i) {
    int largest = i; // Initialize largest as root
    int left = 2*i + 1; // left = 2*i + 1
    int right = 2*i + 2; // right = 2*i + 2

    if (left < n && arr[left] > arr[largest])
        largest = left;

    if (right < n && arr[right] > arr[largest])
        largest = right;

    if (largest != i) {
        swap(&arr[i], &arr[largest]);
        maxHeapify(arr, n, largest);
    }
}

// Function to insert a new node into the MaxHeap
void insertNode(int arr[], int* n, int key) {
    (*n)++;
    int i = *n - 1;
    arr[i] = key;

    while (i != 0 && arr[(i-1)/2] < arr[i]) {   // Fix the max heap property if it is violated
        swap(&arr[i], &arr[(i-1)/2]);
        i = (i-1)/2;
    }
}

// Function to delete the last node from MaxHeap
void deleteNode(int arr[], int* n) {
    int lastElement = arr[*n - 1];
    arr[0] = lastElement;
    (*n)--; 
    maxHeapify(arr, *n, 0);
}

// Function to get the maximum from the heap and delete it
int extractMax(int arr[], int* n) {
    // Store the maximum element
    int root = arr[0];

    // Replace root with last element
    int lastElement = arr[*n - 1];
    arr[0] = lastElement;
    (*n)--;

    // Call max heapify on the reduced heap
    maxHeapify(arr, *n, 0);

    return root;
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; ++i)
        printf("%d ", arr[i]);
    printf("\n");
}

int main(void) {
    int arr[10]; //= {12, 11, 13, 5, 6, 7};
    int capacity = 10;
    int n = 0;

    insertNode(arr, &n, 3);
    insertNode(arr, &n, 9);
    insertNode(arr, &n, 2);
    insertNode(arr, &n, 1);
    insertNode(arr, &n, 4);
    insertNode(arr, &n, 5);

    printArray(arr, n);
    printf("\nExtracted max element: %d\n", extractMax(arr, &n));
    
    printArray(arr, n);
    deleteNode(arr, &n);
    
    printArray(arr, n);

    return 0;
}

Explanation:

  • Insertion: Add the new element at the end. Then move it up while it is smaller than its parent to maintain max heap property.
  • Deletion: Move the last element to the root position and heapify the root node.
  • Extraction of Maximum: This is similar to deletion, but we need to record the root node before replacing it with the last element. The root node was the largest element in the heap.

Summary

Top 10 Interview Questions & Answers on C Programming data structures Heapify and Priority Queue

1. What is a Heap in Data Structures?

Answer:
A heap is a specialized tree-based data structure that satisfies the heap property. In a Max-Heap, the key at the root must be the maximum among all keys present in the binary heap, and the same property must be recursively true for all nodes in the binary heap. In a Min-Heap, the key at the root must be the minimum among all keys present in the binary heap, and the same property must be recursively true for all nodes in the binary heap.

2. What is Heapify?

Answer:
Heapify is the process of converting a binary tree into a heap. It is a crucial operation that helps maintain the heap property. There are two main types of heapify operations:

  • Max-Heapify: Ensures that the subtree rooted at a particular node satisfies the Max-Heap property.
  • Min-Heapify: Ensures that the subtree rooted at a particular node satisfies the Min-Heap property.

3. How does Heapify work in C?

Answer:
Heapify works by progressively moving the root element of a subtree to its correct position to maintain the heap property. Here’s a simple example of how a Max-Heapify function might look in C:

void maxHeapify(int arr[], int n, int i) {
    int largest = i; // Initialize largest as root
    int left = 2 * i + 1; // left = 2*i + 1
    int right = 2 * i + 2; // right = 2*i + 2

    // If left child is larger than root
    if (left < n && arr[left] > arr[largest])
        largest = left;

    // If right child is larger than largest so far
    if (right < n && arr[right] > arr[largest])
        largest = right;

    // If largest is not root
    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;

        // Recursively heapify the affected sub-tree
        maxHeapify(arr, n, largest);
    }
}

4. What is a Priority Queue?

Answer:
A Priority Queue is an abstract data type similar to a regular queue or stack data structure, but each element has a priority associated with it. An element with high priority is served before an element with low priority. Priority queues can be implemented using arrays, linked lists, binary heaps, or balanced binary search trees.

5. How can a priority queue be implemented using a heap in C?

Answer:
A priority queue can be efficiently implemented using a heap data structure. Here’s a basic example of a Max-Priority Queue using a Max-Heap in C:

#include <stdio.h>

int heapSize;

void maxHeapify(int arr[], int i) {
    int largest = i; // Initialize largest as root
    int left = 2 * i + 1;
    int right = 2 * i + 2;

    if (left < heapSize && arr[left] > arr[largest])
        largest = left;

    if (right < heapSize && arr[right] > arr[largest])
        largest = right;

    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;

        maxHeapify(arr, largest);
    }
}

void insertKey(int arr[], int key) {
    heapSize++;
    int i = heapSize - 1;
    arr[i] = key;

    while (i != 0 && arr[(i - 1) / 2] < arr[i]) {
        int swap = arr[i];
        arr[i] = arr[(i - 1) / 2];
        arr[(i - 1) / 2] = swap;
        i = (i - 1) / 2;
    }
}

int extractMax(int arr[]) {
    if (heapSize <= 0)
        return -1;
    if (heapSize == 1) {
        heapSize--;
        return arr[0];
    }

    int root = arr[0];
    arr[0] = arr[heapSize - 1];
    heapSize--;

    maxHeapify(arr, 0);

    return root;
}

6. Can a priority queue be implemented using a Min-Heap?

Answer:
Yes, a priority queue can be implemented using a Min-Heap as well. In this case, the element with the lowest priority is served first. The operations would mirror those used in a Max-Heap but in reverse order.

7. What is the time complexity of heap operations?

Answer:

  • Heapify: O(log n)
  • Insert: O(log n)
  • Extract Max/Min: O(log n)
  • Find Max/Min: O(1) (since the maximum/minimum is always at the root)

8. How do you build a heap from an array?

Answer:
To build a heap from an array, start from the last index of the last non-leaf node and heapify each element up to the root. This process, known as "Bottom-Up Heap Construction," has a time complexity of O(n). In C, this can be implemented as follows:

void buildHeap(int arr[], int n) {
    heapSize = n;
    int startIdx = (n / 2) - 1;

    for (int i = startIdx; i >= 0; i--) {
        maxHeapify(arr, i);
    }
}

9. What are the advantages of using heaps for priority queues?

Answer:

  • Heaps provide an efficient way to maintain priority queues.
  • Insert and extract operations are logarithmic in complexity, making heaps suitable for real-time applications.
  • They are easy to implement using arrays without the need for pointers.

10. What are the differences between Max-Heap and Min-Heap?

Answer:

  • Max-Heap: Each parent node has a value greater than or equal to its child nodes. Used for implementing a Max-Priority Queue.
  • Min-Heap: Each parent node has a value less than or equal to its child nodes. Used for implementing a Min-Priority Queue.

Summary

You May Like This Related .NET Topic

Login to post a comment.