Tutorial Playlist
Implementing a queue using a linked list in C involves utilizing the properties and functionality of linked lists to create a data structure that follows the First-In-First-Out (FIFO) principle. In this comprehensive guide, we have compiled the meaning of queue, linked list, and implementation of queue using linked list in C with examples. So without further ado, dig out this post.
In data structures, a queue is a significant entity that adheres to an age-old principle known as "First-In-First-Out" or FIFO. Just like people patiently forming a line, a queue orchestrates a collection of elements in a specific order, granting the earliest arrival the privilege of leaving first.
Imagine a set-up where you're waiting in a queue to board a rollercoaster. As each person joins the queue, they occupy a position at the end, extending the line further. Similarly, a queue embraces this concept flawlessly in the digital realm of data structures.
1. Enqueue: Picture a new adventurer eagerly joining the line for the rollercoaster. Enqueueing embodies the process of adding an element to the rear of the queue, often referred to as "push" or "insert." The fresh addition graciously assumes its position as the last element in the queue, ready for its turn to come.
2. Dequeue: Eventually, the exhilarating moment arrives when the first person in line steps forward to experience the thrilling rollercoaster ride. Likewise, the dequeue operation corresponds to removing the element at the front of the queue. This act, also known as "pop" or "remove," gracefully eliminates the frontmost element. After its departure, the element succeeding the dequeued one gracefully ascends to occupy the prestigious leading spot.
Queues are invaluable, from scheduling tasks in operating systems and managing network traffic to modeling real-world scenarios like processing print jobs or handling requests in web servers.
Simply put- A linked list is a collection of nodes, each containing a reference to the subsequent node, forming a captivating sequence. A linked list with each node comprising two essential components:
1. Data: At the core of every node lies a precious piece of information, be it an integer, a character, an object, or any other data type that fits the application's needs.
2. Pointer: Serving as a crucial link in the chain, a pointer within each node graciously points to the next node in the sequence. Through this delicate connection, the elements of a linked list forge an orderly procession, unveiling their inherent connectivity.
A linked list embraces a dynamic and flexible nature, offering a captivating way to organize and connect elements. Here are two common variants:
1. Singly Linked List: In this variant, each node contains a data element and a pointer that directs to the subsequent node in the sequence. The last node, also known as the tail, gracefully points to null, signifying the end of the linked list.
2. Doubly Linked List: Elevating the connectivity to new heights, a doubly linked list augments the nodes with an additional pointer. In addition to the forward connection, each node possesses a backward pointer, linking it to the preceding node. This bidirectional path enhances traversal flexibility but incurs a slightly higher memory overhead.
The functionality of linked lists lies in their ability to grow and shrink dynamically. New nodes can be effortlessly inserted or removed, gracefully accommodating the ever-changing demands of the application.
You can carry out the following operations in a connected queue:
Enqueue: By performing this action, an element is added to the back of the queue. It entails building a new node, establishing its element, and updating the rear node and rear pointer's references. Here is an illustration of a Python implementation:
class Node:
  def __init__(self, data):
    self.data = data
    self.next = None
class Queue:
  def __init__(self):
    self.front = None
    self.rear = None
  def enqueue(self, data):
    new_node = Node(data)
    if self.rear is None:
      self.front = self.rear = new_node
    else:
      self.rear.next = new_node
      self.rear = new_node
Dequeue: In this operation, the element at the front of the queue is taken out and returned. It entails deleting the front node by changing the front node and the front pointer to point to the subsequent node in the queue. Here is an illustration of a Python implementation:
class Queue:
  # ... (previous code)
  def dequeue(self):
    if self.front is None:
      return None
    dequeued_data = self.front.data
    self.front = self.front.next
    if self.front is None:
      self.rear = None
    return dequeued_data
IsEmpty: This operation checks to see if the front pointer is null to see if the queue is empty. If it is null, the queue is thought to be empty and without any elements. Here is an illustration of a Python implementation:
class Queue:
  # ... (previous code)
  def is_empty(self):
    return self.front is None
The fundamental operations you can carry out on a connected queue are as follows. In addition, you can use additional operations like traversing the linked list to calculate the size of the queue or peeking (accessing the front element without removing it).
You may use the following algorithm to perform an insertion (enqueue) operation on a linked queue:
1. With the provided data, create a new node.
2. The queue will be empty if both the front and back pointers are null.
3. If not (the queue is not empty), then:
4. The queue's back node is now the new node.
Here's an example implementation of the enqueue operation in Python, assuming you have a Node class and a Queue class with front and rear attributes:
class Node:
  def __init__(self, data):
    self.data = data
    self.next = None
class Queue:
  def __init__(self):
    self.front = None
    self.rear = None
  def enqueue(self, data):
    new_node = Node(data)
    if self.rear is None:
      self.front = self.rear = new_node
    else:
      self.rear.next = new_node
      self.rear = new_node
This approach makes it efficient to add elements to the linked queue's back end. Since updating just the rear pointer is required, the enqueue operation in a linked queue has an O(1) time complexity.
Here's an implementation of a queue using a linked list in C, along with an explanation of each step:
#include <stdio.h>
#include <stdlib.h>
struct Node {
  int data;
  struct Node* next;
};
struct Queue {
  struct Node* front;
  struct Node* rear;
};
struct Queue* createQueue() {
  struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
  queue->front = NULL;
  queue->rear = NULL;
  return queue;
}
int isEmpty(struct Queue* queue) {
  return queue->front == NULL;
}
void enqueue(struct Queue* queue, int data) {
  struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
  newNode->data = data;
  newNode->next = NULL;
  if (isEmpty(queue)) {
    queue->front = queue->rear = newNode;
  } else {
    queue->rear->next = newNode;
    queue->rear = newNode;
  }
}
int dequeue(struct Queue* queue) {
  if (isEmpty(queue)) {
    printf("Error: Queue is empty\n");
    return -1;
  }
  struct Node* temp = queue->front;
  int data = temp->data;
  queue->front = queue->front->next;
  if (queue->front == NULL) {
    queue->rear = NULL;
  }
  free(temp);
  return data;
}
int main() {
  struct Queue* queue = createQueue();
  enqueue(queue, 10);
  enqueue(queue, 20);
  enqueue(queue, 30);
  printf("%d dequeued from the queue\n", dequeue(queue));
  printf("%d dequeued from the queue\n", dequeue(queue));
  printf("%d dequeued from the queue\n", dequeue(queue));
  return 0;
}
With this solution, you can quickly conduct enqueue and dequeue operations and establish a queue using a linked list.
Here's the code for implementing a queue using a linked list in C:
#include <stdio.h>
#include <stdlib.h>
struct Node {
  int data;
  struct Node* next;
};
struct Queue {
  struct Node* front;
  struct Node* rear;
};
struct Queue* createQueue() {
  struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
  queue->front = NULL;
  queue->rear = NULL;
  return queue;
}
int isEmpty(struct Queue* queue) {
  return queue->front == NULL;
}
void enqueue(struct Queue* queue, int data) {
  struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
  newNode->data = data;
  newNode->next = NULL;
  if (isEmpty(queue)) {
    queue->front = newNode;
    queue->rear = newNode;
  } else {
    queue->rear->next = newNode;
    queue->rear = newNode;
  }
}
int dequeue(struct Queue* queue) {
  if (isEmpty(queue)) {
    printf("Error: Queue is empty\n");
    return -1;
  }
  struct Node* temp = queue->front;
  int data = temp->data;
  if (queue->front == queue->rear) {
    queue->front = NULL;
    queue->rear = NULL;
  } else {
    queue->front = queue->front->next;
  }
  free(temp);
  return data;
}
void displayQueue(struct Queue* queue) {
  if (isEmpty(queue)) {
    printf("Queue is empty\n");
    return;
  }
  struct Node* current = queue->front;
  while (current != NULL) {
    printf("%d ", current->data);
    current = current->next;
  }
  printf("\n");
}
int main() {
  struct Queue* queue = createQueue();
  enqueue(queue, 10);
  enqueue(queue, 20);
  enqueue(queue, 30);
  displayQueue(queue);
  printf("%d dequeued from the queue\n", dequeue(queue));
  printf("%d dequeued from the queue\n", dequeue(queue));
  displayQueue(queue);
  return 0;
}
The implementation of queue using linked lists in C++ and C offers a productive and adaptable data structure that complies with the First-In-First-Out (FIFO) concept. A queue is a key component of data structures that arranges elements in a certain order, prioritizing the earliest arrival. On the other hand, linked lists are dynamic structures that are made up of nodes connected by pointers and allow for dynamic growth and contraction.
1. What is the benefit of creating a queue using a linked list?
Constructing a queue using a linked list is advantageous because it offers dynamic memory allocation, enabling the queue to expand or contract as necessary. In situations where the size of the queue is unknown in advance or could alter over time, this flexibility is especially helpful.
2. Can a queue implemented using a linked list handle a large number of elements efficiently?
Yes, a queue that uses a linked list can effectively manage a lot of entries. The enqueue and dequeue operations have an O(1) time complexity, which means they execute in a fixed amount of time regardless of the queue's element count. Because of this, linked list-based queues are appropriate for applications that need quick addition and deletion of entries.
3. Are there any limitations or trade-offs associated with implementing a queue using a linked list?
A linked list implementation of a queue has the drawback of requiring more memory than an array-based solution. Due to the requirement for keeping pointers, each node in the linked list has memory overhead. Additionally, array-based queues may be more cache-friendly than linked list-based queues, which can impact performance in some circumstances.
4. Can a linked list-based queue handle both numeric and non-numeric data types?
Yes, a queue based on linked lists can handle both number and non-numeric data types. The queue can store elements of various types since any data type can be declared for the data field of each node in the linked list. Due to their adaptability, linked list-based queues can be used in a variety of applications that deal with various data types.
PAVAN VADAPALLI
Popular
Talk to our experts. We’re available 24/7.
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
upGrad does not grant credit; credits are granted, accepted or transferred at the sole discretion of the relevant educational institution offering the diploma or degree. We advise you to enquire further regarding the suitability of this program for your academic, professional requirements and job prospects before enrolling. upGrad does not make any representations regarding the recognition or equivalence of the credits or credentials awarded, unless otherwise expressly stated. Success depends on individual qualifications, experience, and efforts in seeking employment.
upGrad does not grant credit; credits are granted, accepted or transferred at the sole discretion of the relevant educational institution offering the diploma or degree. We advise you to enquire further regarding the suitability of this program for your academic, professional requirements and job prospects before enr...