Paramclasses Academy - Blog

Tutorials Details

What is Queue in C with Data Structures and Algorithms ?

What is Queue in C with Data Structures and Algorithms ?

October 17, 2026

Queue in C — Complete Data Structures and Algorithms Tutorial with Examples

SEO Title: Queue in C: Complete DSA Tutorial with Programs and Examples

Suggested URL Slug: /queue-in-c/

Meta Description: Learn Queue in C with complete examples, FIFO concept, array and linked-list implementation, enqueue, dequeue, circular queue, deque, priority queue, and C programs with output.

Module 07: Queue in C

Introduction

A Queue is a linear data structure that follows the FIFO (First In, First Out) principle. The element inserted first is the element removed first.

Queues are used in CPU scheduling, printer management, task processing, customer service systems, network communication, and many other applications.

For example, imagine a line of customers waiting at a ticket counter. The customer who arrives first is generally served first. A Queue works in a similar way.

1. Introduction to Queue

A Queue supports two primary operations:

  • Enqueue: Insert an element at the rear of the Queue.

  • Dequeue: Remove an element from the front of the Queue.

Two important pointers or indices are used:

  • FRONT: Identifies the first element that will be removed.

  • REAR: Identifies the last element that was inserted.

Example

Suppose the Queue contains:

FRONT → [10] [20] [30] ← REAR

If we enqueue 40, the Queue becomes:

FRONT → [10] [20] [30] [40] ← REAR

If we dequeue once, 10 is removed:

FRONT → [20] [30] [40] ← REAR

The first inserted element, 10, was the first element removed.

2. FIFO Concept

FIFO stands for First In, First Out.

Consider the following operations:

  1. Enqueue 10

  2. Enqueue 20

  3. Enqueue 30

  4. Dequeue once

After the first three operations, the Queue contains 10, 20, 30. The dequeue operation removes 10, leaving 20, 30.

FIFO Example in C

#include 

int main(void) {
    int queue[5];
    int front = 0, rear = -1;

    queue[++rear] = 10;
    queue[++rear] = 20;
    queue[++rear] = 30;

    printf("Removed: %d\n", queue[front++]);

    printf("Remaining elements: ");
    for (int i = front; i <= rear; i++) {
        printf("%d ", queue[i]);
    }

    printf("\n");
    return 0;
}

Output:

Removed: 10
Remaining elements: 20 30

This example demonstrates FIFO. It is a simplified demonstration rather than a complete Queue implementation because it does not reuse freed array positions or check capacity.

3. Queue Using Arrays

An array can store Queue elements in contiguous memory locations. Two indices, front and rear, track the Queue's boundaries.

In a simple linear array Queue:

  • Initially, front = -1 and rear = -1.

  • On the first insertion, both become 0.

  • Each subsequent insertion increments rear.

  • Each removal increments front.

  • The Queue is full when rear == SIZE - 1.

  • The Queue is empty when front == -1 or front > rear.

A basic array Queue is easy to implement, but once rear reaches the last array position, it cannot reuse earlier empty positions. A Circular Queue solves this limitation.

Complete Array Queue Program in C

#include 

#define SIZE 5

int queue[SIZE];
int front = -1;
int rear = -1;

int isEmpty(void) {
    return front == -1 || front > rear;
}

int isFull(void) {
    return rear == SIZE - 1;
}

void enqueue(int value) {
    if (isFull()) {
        printf("Queue Overflow\n");
        return;
    }

    if (front == -1) {
        front = 0;
    }

    queue[++rear] = value;
    printf("%d inserted\n", value);
}

void dequeue(void) {
    if (isEmpty()) {
        printf("Queue Underflow\n");
        return;
    }

    printf("%d removed\n", queue[front]);

    if (front == rear) {
        front = rear = -1;
    } else {
        front++;
    }
}

void display(void) {
    if (isEmpty()) {
        printf("Queue is empty\n");
        return;
    }

    printf("Queue: ");
    for (int i = front; i <= rear; i++) {
        printf("%d ", queue[i]);
    }
    printf("\n");
}

int main(void) {
    enqueue(10);
    enqueue(20);
    enqueue(30);

    display();
    dequeue();
    display();

    return 0;
}

Output:

10 inserted
20 inserted
30 inserted
Queue: 10 20 30
10 removed
Queue: 20 30

Time complexity:

Operation Complexity
Enqueue O(1)
Dequeue O(1)
Display O(n)

Here, n is the number of elements displayed.

4. Queue Using Linked Lists

A linked-list Queue consists of nodes. Each node stores a value and a pointer to the next node.

Two pointers are maintained:

  • front: Points to the first node.

  • rear: Points to the last node.

During enqueue, a new node is attached at the rear. During dequeue, the front node is removed.

Unlike a fixed-size array Queue, a linked-list Queue can grow dynamically until memory allocation fails.

Queue Using Linked Lists in C

#include 
#include 

struct Node {
    int data;
    struct Node *next;
};

struct Node *front = NULL;
struct Node *rear = NULL;

void enqueue(int value) {
    struct Node *newNode = malloc(sizeof(struct Node));

    if (newNode == NULL) {
        printf("Memory allocation failed\n");
        return;
    }

    newNode->data = value;
    newNode->next = NULL;

    if (rear == NULL) {
        front = rear = newNode;
    } else {
        rear->next = newNode;
        rear = newNode;
    }

    printf("%d inserted\n", value);
}

void dequeue(void) {
    if (front == NULL) {
        printf("Queue Underflow\n");
        return;
    }

    struct Node *temp = front;
    printf("%d removed\n", temp->data);

    front = front->next;

    if (front == NULL) {
        rear = NULL;
    }

    free(temp);
}

void display(void) {
    struct Node *temp = front;

    if (temp == NULL) {
        printf("Queue is empty\n");
        return;
    }

    printf("Queue: ");
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

void freeQueue(void) {
    while (front != NULL) {
        struct Node *temp = front;
        front = front->next;
        free(temp);
    }
    rear = NULL;
}

int main(void) {
    enqueue(100);
    enqueue(200);
    enqueue(300);

    display();
    dequeue();
    display();

    freeQueue();
    return 0;
}

Output:

100 inserted
200 inserted
300 inserted
Queue: 100 200 300
100 removed
Queue: 200 300

Array Queue vs Linked-List Queue

Feature Array Queue Linked-List Queue
Storage Contiguous array Dynamically allocated nodes
Capacity Fixed in this implementation Limited by available memory
Enqueue O(1) until full O(1) with a rear pointer
Dequeue O(1) O(1)
Memory overhead Low Extra pointer per node
Reuse of removed positions Not in a simple linear Queue Memory is freed when removed

5. Enqueue and Dequeue Operations

Enqueue

Enqueue inserts an element at the rear of the Queue.

Algorithm:

  1. Check whether the Queue is full.

  2. If full, report overflow.

  3. If the Queue is empty, initialize front.

  4. Insert the new value at the rear.

  5. Update rear.

Dequeue

Dequeue removes the element at the front.

Algorithm:

  1. Check whether the Queue is empty.

  2. If empty, report underflow.

  3. Read and remove the front element.

  4. Advance front.

  5. If the last element was removed, reset both indices.

Example

Starting Queue:

FRONT → [10] [20] [30] ← REAR

After ENQUEUE(40):

FRONT → [10] [20] [30] [40] ← REAR

After DEQUEUE():

FRONT → [20] [30] [40] ← REAR

Both enqueue and dequeue take O(1) time when implemented with appropriate front and rear tracking.

6. Circular Queue

A Circular Queue connects the last array position logically back to the first position. This allows freed array positions to be reused.

In a circular array of size SIZE, the next position is calculated using:

(rear + 1) % SIZE

The Queue is full when:

(rear + 1) % SIZE == front

The Queue is empty when:

front == -1

Why Do We Need a Circular Queue?

In a simple linear Queue, removing elements from the front does not free positions for new insertions if rear has already reached the end of the array. This can waste usable capacity.

A Circular Queue reuses those positions by wrapping around to the beginning.

Circular Queue Program in C

#include 

#define SIZE 5

int queue[SIZE];
int front = -1;
int rear = -1;

int isEmpty(void) {
    return front == -1;
}

int isFull(void) {
    return (rear + 1) % SIZE == front;
}

void enqueue(int value) {
    if (isFull()) {
        printf("Circular Queue Overflow\n");
        return;
    }

    if (isEmpty()) {
        front = rear = 0;
    } else {
        rear = (rear + 1) % SIZE;
    }

    queue[rear] = value;
    printf("%d inserted\n", value);
}

void dequeue(void) {
    if (isEmpty()) {
        printf("Circular Queue Underflow\n");
        return;
    }

    printf("%d removed\n", queue[front]);

    if (front == rear) {
        front = rear = -1;
    } else {
        front = (front + 1) % SIZE;
    }
}

void display(void) {
    if (isEmpty()) {
        printf("Queue is empty\n");
        return;
    }

    printf("Queue: ");
    int i = front;

    while (1) {
        printf("%d ", queue[i]);

        if (i == rear) {
            break;
        }

        i = (i + 1) % SIZE;
    }

    printf("\n");
}

int main(void) {
    enqueue(10);
    enqueue(20);
    enqueue(30);
    enqueue(40);

    dequeue();
    dequeue();

    enqueue(50);
    enqueue(60);

    display();
    return 0;
}

Output:

10 inserted
20 inserted
30 inserted
40 inserted
10 removed
20 removed
50 inserted
60 inserted
Queue: 30 40 50 60

Circular Queue Complexity

Operation Complexity
Enqueue O(1)
Dequeue O(1)
Display O(n)

7. Deque (Double-Ended Queue)

A Deque, pronounced “deck,” stands for Double-Ended Queue. It allows insertion and deletion at both ends.

Unlike a standard Queue, which normally inserts at the rear and removes from the front, a Deque supports more flexible operations.

Common operations include:

  • insertFront() — insert at the front.

  • insertRear() — insert at the rear.

  • deleteFront() — remove from the front.

  • deleteRear() — remove from the rear.

Types of Deque

1. Input-Restricted Deque

Insertion is allowed at only one end, while deletion is allowed at both ends.

2. Output-Restricted Deque

Deletion is allowed at only one end, while insertion is allowed at both ends.

Simple Deque Implementation Using a Circular Array

#include 

#define SIZE 5

int deque[SIZE];
int front = -1;
int rear = -1;

int isEmpty(void) {
    return front == -1;
}

int isFull(void) {
    return (rear + 1) % SIZE == front;
}

void insertFront(int value) {
    if (isFull()) {
        printf("Deque Overflow\n");
        return;
    }

    if (isEmpty()) {
        front = rear = 0;
    } else {
        front = (front - 1 + SIZE) % SIZE;
    }

    deque[front] = value;
    printf("%d inserted at front\n", value);
}

void insertRear(int value) {
    if (isFull()) {
        printf("Deque Overflow\n");
        return;
    }

    if (isEmpty()) {
        front = rear = 0;
    } else {
        rear = (rear + 1) % SIZE;
    }

    deque[rear] = value;
    printf("%d inserted at rear\n", value);
}

void deleteFront(void) {
    if (isEmpty()) {
        printf("Deque Underflow\n");
        return;
    }

    printf("%d deleted from front\n", deque[front]);

    if (front == rear) {
        front = rear = -1;
    } else {
        front = (front + 1) % SIZE;
    }
}

void deleteRear(void) {
    if (isEmpty()) {
        printf("Deque Underflow\n");
        return;
    }

    printf("%d deleted from rear\n", deque[rear]);

    if (front == rear) {
        front = rear = -1;
    } else {
        rear = (rear - 1 + SIZE) % SIZE;
    }
}

void display(void) {
    if (isEmpty()) {
        printf("Deque is empty\n");
        return;
    }

    printf("Deque: ");
    int i = front;

    while (1) {
        printf("%d ", deque[i]);

        if (i == rear) {
            break;
        }

        i = (i + 1) % SIZE;
    }

    printf("\n");
}

int main(void) {
    insertRear(20);
    insertRear(30);
    insertFront(10);

    display();

    deleteRear();
    display();

    return 0;
}

Output:

20 inserted at rear
30 inserted at rear
10 inserted at front
Deque: 10 20 30
30 deleted from rear
Deque: 10 20

All four Deque operations run in O(1) time in this circular-array implementation.

8. Priority Queue

A Priority Queue is a data structure in which each element is associated with a priority. Elements are removed according to priority rather than simply according to arrival time.

For example, in a hospital emergency department, a critical patient may be treated before a patient with a minor injury, even if the second patient arrived earlier.

Priority rules vary by implementation. In this example, a smaller priority number means higher priority.

Example

Element Priority
Task A 3
Task B 1
Task C 2

Removal order:

  1. Task B — priority 1

  2. Task C — priority 2

  3. Task A — priority 3

Priority Queue Using an Array in C

This basic implementation removes the element with the smallest priority number. It uses a simple unsorted array, making insertion O(1) and removal O(n).

#include 

#define SIZE 5

struct Item {
    int value;
    int priority;
};

struct Item pq[SIZE];
int count = 0;

void insert(int value, int priority) {
    if (count == SIZE) {
        printf("Priority Queue Overflow\n");
        return;
    }

    pq[count].value = value;
    pq[count].priority = priority;
    count++;

    printf("Inserted %d with priority %d\n", value, priority);
}

void deleteHighestPriority(void) {
    if (count == 0) {
        printf("Priority Queue Underflow\n");
        return;
    }

    int best = 0;

    for (int i = 1; i < count; i++) {
        if (pq[i].priority < pq[best].priority) {
            best = i;
        }
    }

    printf("Removed: %d (priority %d)\n",
           pq[best].value, pq[best].priority);

    for (int i = best; i < count - 1; i++) {
        pq[i] = pq[i + 1];
    }

    count--;
}

void display(void) {
    if (count == 0) {
        printf("Priority Queue is empty\n");
        return;
    }

    printf("Items: ");
    for (int i = 0; i < count; i++) {
        printf("[%d, priority %d] ",
               pq[i].value, pq[i].priority);
    }
    printf("\n");
}

int main(void) {
    insert(100, 3);
    insert(200, 1);
    insert(300, 2);

    display();
    deleteHighestPriority();
    display();

    return 0;
}

Output:

Inserted 100 with priority 3
Inserted 200 with priority 1
Inserted 300 with priority 2
Items: [100, priority 3] [200, priority 1] [300, priority 2]
Removed: 200 (priority 1)
Items: [100, priority 3] [300, priority 2]

Priority Queue Complexity

Operation Unsorted Array Implementation
Insert O(1)
Remove highest priority O(n)
Display O(n)

A binary heap is commonly used to implement a Priority Queue more efficiently, providing O(log n) insertion and removal, with O(1) access to the highest-priority element.

Queue Types Comparison

Type Main Principle Typical Use
Linear Queue FIFO Basic task processing
Circular Queue FIFO with wraparound Buffers and streaming
Deque Insert/delete at both ends Flexible scheduling
Priority Queue Removal based on priority CPU scheduling and event processing

Real-World Applications of Queues

  1. CPU Scheduling: Processes wait for CPU time.

  2. Printer Scheduling: Print jobs wait in a queue.

  3. Network Buffers: Packets wait to be processed or transmitted.

  4. Customer Service: Requests are handled in arrival order.

  5. Breadth-First Search: A Queue processes graph or tree nodes level by level.

  6. Task Scheduling: Background jobs wait for execution.

  7. Message Systems: Messages can be held until a consumer processes them.

  8. Traffic Simulation: Vehicles can be modeled as waiting in a line.

Key Takeaways

  • A Queue follows FIFO: First In, First Out.

  • Enqueue inserts an element at the rear.

  • Dequeue removes an element from the front.

  • Arrays and linked lists are common Queue implementations.

  • A simple linear array Queue can waste space after deletions.

  • A Circular Queue reuses array positions through wraparound.

  • A Deque supports insertion and deletion at both ends.

  • A Priority Queue removes elements according to priority.

  • Queue operations can often run in O(1) time when the data structure is designed appropriately.

Conclusion

Queues are essential linear data structures in C and DSA. Understanding FIFO, enqueue, dequeue, array-based queues, linked-list queues, circular queues, Deques, and Priority Queues provides a strong foundation for more advanced algorithms and system design.

Practice each implementation, compile the programs, and test edge cases such as empty queues, full queues, and removing the last remaining element.

Next Module: Module 08 — Trees in C: Binary Trees, Binary Search Trees, Tree Traversals, AVL Tree Basics, and Heap Data Structure.