For working professionals
For fresh graduates
More
5. Array in C
13. Boolean in C
18. Operators in C
33. Comments in C
38. Constants in C
41. Data Types in C
49. Double In C
58. For Loop in C
60. Functions in C
70. Identifiers in C
81. Linked list in C
83. Macros in C
86. Nested Loop in C
97. Pseudo-Code In C
100. Recursion in C
103. Square Root in C
104. Stack in C
106. Static function in C
107. Stdio.h in C
108. Storage Classes in C
109. strcat() in C
110. Strcmp in C
111. Strcpy in C
114. String Length in C
115. String Pointer in C
116. strlen() in C
117. Structures in C
119. Switch Case in C
120. C Ternary Operator
121. Tokens in C
125. Type Casting in C
126. Types of Error in C
127. Unary Operator in C
128. Use of C Language
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.
Take a Free C Programming Quiz
Answer quick questions and assess your C programming knowledge
Author
Start Learning For Free
Explore Our Free Software Tutorials and Elevate your Career.
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.