High Profile Call Girls Nagpur Isha Call 7001035870 Meet With Nagpur Escorts
DS UNIT3_LINKED LISTS.docx
1. Linked list Data Structure
A linked list is a linear data structure that includes a series of connected nodes. Here, each node
stores the data and the address of the next node. For example,
Linked list Data Structure
You have to start somewhere, so we give the address of the first node a special name
called HEAD. Also, the last node in the linked list can be identified because its next portion
points to NULL.
Linked lists can be of multiple types: singly, doubly, and circular linked list. In this article, we
will focus on the singly linked list.
Representation of Linked List
Let's see how each node of the linked list is represented. Each node consists:
A data item
An address of another node
We wrap both the data item and the next node reference in a struct as:
struct node
{
int data;
struct node *next;
};
Understanding the structure of a linked list node is the key to having a grasp on it.
Each struct node has a data item and a pointer to another struct node. Let us create a simple
Linked List with three items to understand how this works.
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
2. /* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
/* Assign data values */
one->data = 1;
two->data = 2;
three->data=3;
/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;
/* Save address of first node in head */
head = one;
Linked list Representation
if you wanted to put an element 4 between 1 and 2, the steps would be:
Create a new struct node and allocate memory to it.
Add its data value as 4
Point its next pointer to the struct node containing 2 as the data value
Change the next pointer of "1" to the node we just created.
Doing something similar in an array would have required shifting the positions of all the
subsequent elements.
3. Linked list implementation in C
#include <stdio.h>
#include <stdlib.h>
// Creating a node
struct node {
int value;
struct node *next;
};
// print the linked list value
void printLinkedlist(struct node *p) {
while (p != NULL) {
printf("%d ", p->value);
p = p->next;
}
}
int main() {
// Initialize nodes
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
// Allocate memory
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
4. // Assign value values
one->value = 1;
two->value = 2;
three->value = 3;
// Connect nodes
one->next = two;
two->next = three;
three->next = NULL;
// printing node-value
head = one;
printLinkedlist(head);
}
Allocating and Freeing of Dynamic variables:
Since C is a structured language, it has some fixed rules for programming. One of them includes
changing the size of an array. An array is a collection of items stored at contiguous memory
locations.
As can be seen, the length (size) of the array above is 9. But what if there is a requirement to
change this length (size)? For example,
5. If there is a situation where only 5 elements are needed to be entered in this array. In this case,
the remaining 4 indices are just wasting memory in this array. So there is a requirement to
lessen the length (size) of the array from 9 to 5.
Take another situation. In this, there is an array of 9 elements with all 9 indices filled. But there
is a need to enter 3 more elements in this array. In this case, 3 indices more are required. So the
length (size) of the array needs to be changed from 9 to 12.
This procedure is referred to as Dynamic Memory Allocation in C.
Therefore, C Dynamic Memory Allocation can be defined as a procedure in which the size of
a data structure (like Array) is changed during the runtime.
C provides some functions to achieve these tasks. There are 4 library functions provided by C
defined under <stdlib.h> header file to facilitate dynamic memory allocation in C
programming. They are:
malloc()
calloc()
free()
realloc()
Let’s look at each of them in greater detail.
1.C malloc() method
The “malloc” or “memory allocation” method in C is used to dynamically allocate a single
large block of memory with the specified size. It returns a pointer of type void which can be
cast into a pointer of any form. It doesn’t Initialize memory at execution time so that it has
initialized each block with the default garbage value initially.
Syntax of malloc() in C
ptr = (cast-type*) malloc(byte-size)
For Example:
ptr = (int*) malloc(100 * sizeof(int));
Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the
pointer ptr holds the address of the first byte in the allocated memory.
6. If space is insufficient, allocation fails and returns a NULL pointer.
Example of malloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
printf("Enter number of elements:");
scanf("%d",&n);
printf("Entered number of elements: %dn", n);
// Dynamically allocate memory using malloc()
ptr = (int*)malloc(n * sizeof(int));
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.n");
exit(0);
}
else {
7. // Memory has been successfully allocated
printf("Memory successfully allocated using malloc.n");
// Get the elements of the array
for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}
return 0;
}
Output
Enter number of elements: 5
Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5,
C calloc() method
“calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified
number of blocks of memory of the specified type. it is very much similar to malloc() but has
two different points and these are:
It initializes each block with a default value ‘0’.
It has two parameters or arguments as compare to malloc().
Syntax of calloc() in C
8. ptr = (cast-type*)calloc(n, element-size);
here, n is the no. of elements and element-size is the size of each element.
For Example:
ptr = (float*) calloc(25, sizeof(float));
This statement allocates contiguous space in memory for 25 elements each with the size of
the float.
If space is insufficient, allocation fails and returns a NULL pointer.
Example of calloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %dn", n);
9. // Dynamically allocate memory using calloc()
ptr = (int*)calloc(n, sizeof(int));
// Check if the memory has been successfully
// allocated by calloc or not
if (ptr == NULL) {
printf("Memory not allocated.n");
exit(0);
}
else {
// Memory has been successfully allocated
printf("Memory successfully allocated using calloc.n");
// Get the elements of the array
for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
}
return 0;
}
Output
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
10. C free() method
“free” method in C is used to dynamically de-allocate the memory. The memory allocated
using functions malloc() and calloc() is not de-allocated on their own. Hence the free() method
is used, whenever the dynamic memory allocation takes place. It helps to reduce wastage of
memory by freeing it.
Syntax of free() in C
free(ptr);
Example of free() in C
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int *ptr, *ptr1;
int n, i;
// Get the number of elements for the array
11. n = 5;
printf("Enter number of elements: %dn", n);
// Dynamically allocate memory using malloc()
ptr = (int*)malloc(n * sizeof(int));
// Dynamically allocate memory using calloc()
ptr1 = (int*)calloc(n, sizeof(int));
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL || ptr1 == NULL) {
printf("Memory not allocated.n");
exit(0);
}
else {
// Memory has been successfully allocated
printf("Memory successfully allocated using malloc.n");
// Free the memory
free(ptr);
printf("Malloc Memory successfully freed.n");
// Memory has been successfully allocated
printf("nMemory successfully allocated using calloc.n");
// Free the memory
free(ptr1);
printf("Calloc Memory successfully freed.n");
}
return 0;
}
12. Output
Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc Memory successfully freed.
Memory successfully allocated using calloc.
Calloc Memory successfully freed.
C realloc() method:
“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation
of a previously allocated memory. In other words, if the memory previously allocated with the
help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate memory.
Re-allocation of memory maintains the already present value and new blocks will be initialized
with the default garbage value.
Syntax of realloc() in C
ptr = realloc(ptr, newSize);
where ptr is reallocated with new size 'newSize'.
If space is insufficient, allocation fails and returns a NULL pointer.
13. Example of realloc() in C
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %dn", n);
// Dynamically allocate memory using calloc()
ptr = (int*)calloc(n, sizeof(int));
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL) {
printf("Memory not allocated.n");
exit(0);
}
else {
// Memory has been successfully allocated
14. printf("Memory successfully allocated using calloc.n");
// Get the elements of the array
for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
// Get the new size for the array
n = 10;
printf("nnEnter the new size of the array: %dn", n);
// Dynamically re-allocate memory using realloc()
ptr = (int*)realloc(ptr, n * sizeof(int));
// Memory has been successfully allocated
printf("Memory successfully re-allocated using realloc.n");
// Get the new elements of the array
for (i = 5; i < n; ++i) {
ptr[i] = i + 1;
}
// Print the elements of the array
15. printf("The elements of the array are: ");
for (i = 0; i < n; ++i) {
printf("%d, ", ptr[i]);
}
free(ptr);
}
return 0;
}
Output
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
Enter the new size of the array: 10
Memory successfully re-allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
One another example for realloc() method is:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int index = 0, i = 0, n,
*marks; // this marks pointer hold the base address
// of the block created
int ans;
16. marks = (int*)malloc(sizeof(
int)); // dynamically allocate memory using malloc
// check if the memory is successfully allocated by
// malloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
// memory has successfully allocated
printf("Memory has been successfully allocated by "
"using mallocn");
printf("n marks = %pcn",
marks); // print the base or beginning
// address of allocated memory
do {
printf("n Enter Marksn");
scanf("%d", &marks[index]); // Get the marks
printf("would you like to add more(1/0): ");
scanf("%d", &ans);
if (ans == 1) {
index++;
marks = (int*)realloc(
marks,
(index + 1)
* sizeof(
int)); // Dynamically reallocate
// memory by using realloc
// check if the memory is successfully
17. // allocated by realloc or not?
if (marks == NULL) {
printf("memory cannot be allocated");
}
else {
printf("Memory has been successfully "
"reallocated using realloc:n");
printf(
"n base address of marks are:%pc",
marks); ////print the base or
///beginning address of
///allocated memory
}
}
} while (ans == 1);
// print the marks of the students
for (i = 0; i <= index; i++) {
printf("marks of students %d are: %dn ", i,
marks[i]);
}
free(marks);
}
return 0;
}
Output:
18. Linked Lists using Dynamic Variables in C:
Here are the key theoretical concepts related to linked lists using dynamic variables:
Node Structure:
In C, a basic node structure is typically defined to hold the data and a pointer to the next node.
struct Node
{
int data; struct Node* next;
};
Dynamic Memory Allocation:
Nodes in a linked list are dynamically allocated using functions like malloc in C. This allows
the list to grow or shrink as needed.
struct Node* newNode = (structNode*)malloc(sizeof(struct Node));
Head Pointer:
The linked list is usually represented by a head pointer, pointing to the first node.
struct Node* head = NULL;
19. Insertion:
Nodes can be inserted at the beginning, middle, or end of the list.
Inserting at the beginning involves creating a new node, setting its next to the current head, and
updating the head to the new node.
struct Node* insertAtBeginning(struct Node* head, int value)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = value;
newNode->next = head;
head = newNode;
return head;
}
Traversal:
Traversing the linked list involves moving from one node to the next until the end is reached
(when next is NULL).
void printLinkedList(struct Node* head)
{
struct Node* current = head;
while (current != NULL)
{
printf("%d -> ", current->data);
current = current->next;
}
printf("NULLn"); }
20. Deletion:
Nodes can be deleted by updating pointers. For example, to delete a node, set the next pointer
of its predecessor to skip the node.
Advantages:
Dynamic memory allocation allows for efficient use of memory.
Insertion and deletion operations are faster compared to arrays since there's no need to shift
elements.
Disadvantages:
Random access is not possible; you must traverse the list to find an element.
More memory is consumed compared to arrays due to the storage of pointers.
Below is a simple example of implementing a linked list using dynamic variables in the C
programming language. This example defines a Node structure to represent each element in
the linked list.
#include <stdio.h>
#include <stdlib.h>
// Define the Node structure
struct Node {
int data;
struct Node* next;
};
// Function to insert a new node at the beginning of the linked list
struct Node* insertAtBeginning(struct Node* head, int value) {
// Create a new node
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
// Check if memory allocation is successful
if (newNode == NULL) {
printf("Memory allocation failed.n");
21. exit(1);
}
// Set data and next pointer
newNode->data = value;
newNode->next = head;
// Update the head to point to the new node
head = newNode;
return head;
}
// Function to print the linked list
void printLinkedList(struct Node* head) {
struct Node* current = head;
// Traverse the linked list
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULLn");
}
// Main function
int main() {
// Initialize an empty linked list
struct Node* head = NULL;
22. // Insert elements at the beginning
head = insertAtBeginning(head, 3);
head = insertAtBeginning(head, 7);
head = insertAtBeginning(head, 1);
// Print the linked list
printf("Linked List: ");
printLinkedList(head);
return 0;
}
Linked List Operations: Traverse, Insert and Delete
There are various linked list operations that allow us to perform different actions on linked
lists. For example, the insertion operation adds a new element to the linked list.
Here's a list of basic linked list operations that we will cover in this article.
Traversal - access each element of the linked list
Insertion - adds a new element to the linked list
Deletion - removes the existing elements
Search - find a node in the linked list
Sort - sort the nodes of the linked list
Things to Remember about Linked List
head points to the first node of the linked list
next pointer of the last node is NULL, so if the next current node is NULL, we have reached
the end of the linked list.
In all of the examples, we will assume that the linked list has three nodes 1 --->2 --->3 with
node structure as below:
struct node {
23. int data;
struct node *next;
};
Traverse a Linked List
Displaying the contents of a linked list is very simple. We keep moving the temp node to the
next one and display its contents.
When temp is NULL, we know that we have reached the end of the linked list so we get out of
the while loop.
struct node *temp = head;
printf("nnList elements are - n");
while(temp != NULL) {
printf("%d --->",temp->data);
temp = temp->next;
}
The output of this program will be:
List elements are -
1 --->2 --->3 --->
Insert Elements to a Linked List
You can add elements to either the beginning, middle or end of the linked list.
1. Insert at the beginning
Allocate memory for new node
Store data
Change next of new node to point to head
Change head to point to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = head;
head = newNode;
24. 2. Insert at the End
Allocate memory for new node
Store data
Traverse to last node
Change next of last node to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = NULL;
struct node *temp = head;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = newNode;
3. Insert at the Middle
Allocate memory and store data for new node
Traverse to node just before the required position of new node
Change next pointers to include new node in between
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
struct node *temp = head;
for(int i=2; i < position; i++) {
if(temp->next != NULL) {
temp = temp->next;
}
}
25. newNode->next = temp->next;
temp->next = newNode;
Delete from a Linked List
You can delete either from the beginning, end or from a particular position.
1. Delete from beginning
Point head to the second node
head = head->next;
2. Delete from end
Traverse to second last element
Change its next pointer to null
struct node* temp = head;
while(temp->next->next!=NULL){
temp = temp->next;
}
temp->next = NULL;
3. Delete from middle
Traverse to element before the element to be deleted
Change next pointers to exclude the node from the chain
for(int i=2; i< position; i++) {
if(temp->next!=NULL) {
temp = temp->next;
}
}
temp->next = temp->next->next;
Search an Element on a Linked List
You can search an element on a linked list using a loop using the following steps. We are
finding item on a linked list.
Make head as the current node.
Run a loop until the current node is NULL because the last element points to NULL.
26. In each iteration, check if the key of the node is equal to item. If it the key matches the item,
return true otherwise return false.
// Search a node
bool searchNode(struct Node** head_ref, int key) {
struct Node* current = *head_ref;
while (current != NULL) {
if (current->data == key) return true;
current = current->next;
}
return false;
}
Sort Elements of a Linked List
We will use a simple sorting algorithm, Bubble Sort, to sort the elements of a linked list in
ascending order below.
Make the head as the current node and create another node index for later use.
If head is null, return.
Else, run a loop till the last node (i.e. NULL).
In each iteration, follow the following step 5-6.
Store the next node of current in index.
Check if the data of the current node is greater than the next node. If it is greater,
swap current and index.
Check the article on bubble sort for better understanding of its working.
// Sort the linked list
void sortLinkedList(struct Node** head_ref) {
struct Node *current = *head_ref, *index = NULL;
int temp;
if (head_ref == NULL) {
return;
} else {
27. while (current != NULL) {
// index points to the node next to current
index = current->next;
while (index != NULL) {
if (current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
LinkedList Operations in C.
// Linked list operations in C
#include <stdio.h>
#include <stdlib.h>
// Create a node
struct Node {
int data;
struct Node* next;
};
// Insert at the beginning
void insertAtBeginning(struct Node** head_ref, int new_data) {
// Allocate memory to a node
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
28. // insert the data
new_node->data = new_data;
new_node->next = (*head_ref);
// Move head to new node
(*head_ref) = new_node;
}
// Insert a node after a node
void insertAfter(struct Node* prev_node, int new_data) {
if (prev_node == NULL) {
printf("the given previous node cannot be NULL");
return;
}
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
}
// Insert the the end
void insertAtEnd(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *head_ref; /* used in step 5*/
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) {
*head_ref = new_node;
return;
}
while (last->next != NULL) last = last->next;
last->next = new_node;
29. return;
}
// Delete a node
void deleteNode(struct Node** head_ref, int key) {
struct Node *temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next;
free(temp);
return;
}
// Find the key to be deleted
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
// If the key is not present
if (temp == NULL) return;
// Remove the node
prev->next = temp->next;
free(temp);
}
// Search a node
int searchNode(struct Node** head_ref, int key) {
struct Node* current = *head_ref;
while (current != NULL) {
if (current->data == key) return 1;
current = current->next;
30. }
return 0;
}
// Sort the linked list
void sortLinkedList(struct Node** head_ref) {
struct Node *current = *head_ref, *index = NULL;
int temp;
if (head_ref == NULL) {
return;
} else {
while (current != NULL) {
// index points to the node next to current
index = current->next;
while (index != NULL) {
if (current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
// Print the linked list
void printList(struct Node* node) {
while (node != NULL) {
31. printf(" %d ", node->data);
node = node->next;
}
}
// Driver program
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 1);
insertAtBeginning(&head, 2);
insertAtBeginning(&head, 3);
insertAtEnd(&head, 4);
insertAfter(head->next, 5);
printf("Linked list: ");
printList(head);
printf("nAfter deleting an element: ");
deleteNode(&head, 3);
printList(head);
int item_to_find = 3;
if (searchNode(&head, item_to_find)) {
printf("n%d is found", item_to_find);
} else {
printf("n%d is not found", item_to_find);
}
sortLinkedList(&head);
printf("nSorted List: ");
32. printList(head);
}
Stacks and Queues as List in C :
In this Stacks and Queues in C tutorial, we will discuss:
Stack in C
Array implementation of a Stack
Linked list implementation of a Stack
Applications of Stack
Queue in C
Array implementation of a Queue
Linked list implementation of a Queue
Circular Queue
Applications of Queue
1. What is Stack in C?
33. A stack in C is nothing but a linear data structure that follows the LIFO rule (Last In First Out).
In a stack, both insertion and deletion take place from just one end, that is, from the top.
Linked List Implementation of Stack in C:
Insertion
This is how we can insert elements into the stack in C:
void push ()
{
int data;
struct node *pointer = (struct node*)malloc(sizeof(struct node));
if(pointer == NULL)
{
printf("Stack overflow");
}
34. else
{
printf("Enter the element to be inserted: ");
scanf("%d",&data);
if(temp == NULL)
{
pointer -> data = data;
pointer -> next = NULL;
temp = pointer;
}
else
{
pointer -> data = data;
pointer -> next = temp;
temp = pointer;
}
}
}
Deletion:
void pop()
{
int item;
struct node *pointer;
if (temp == NULL)
{
printf("Stack Underflown");
}
else
35. {
item = temp -> data;
pointer = temp;
temp = temp -> next;
free(pointer);
printf("The deleted item is %dn",item);
}
}
Display:
This is how we display the elements of a stack:
void display()
{
int i;
struct node *pointer;
pointer = temp;
if(pointer == NULL)
{
printf("Stack underflown");
}
else
{
printf("The elements of the stack are:n");
while(pointer!= NULL)
{
printf("%dn",pointer -> data);
pointer = pointer -> next;
}
}
36. }
Here is a code in C that illustrates the linked list implementation of arrays:
#include <stdio.h>
#include <stdlib.h>
void push(); // Function used to insert the element into the stack
void pop(); // Function used to delete the elememt from the stack
void display(); // Function used to display all the elements in the stack according to LIFO rule
struct node
{
int data;
struct node *next;
};
struct node *temp;
int main()
{
printf("Welcome to DataFlair tutorials!nn");
int choice;
printf ("LINKED LIST IMPLEMENTATION USING STACKSnn");
do
{
printf("1. Insertn2. Deleten3. Displayn4. Exitnn");
printf("Enter your choice:");
scanf("%d",&choice);
37. switch(choice)
{
case 1:
push();
break;
case 2:
pop();
break;
case 3:
display();
break;
case 4:
exit(0);
break;
default:
printf("Sorry, invalid choice!n");
break;
}
} while(choice!=4);
return 0;
}
void push ()
{
int data;
struct node *pointer = (struct node*)malloc(sizeof(struct node));
if(pointer == NULL)
{
printf("Stack overflow");
38. }
else
{
printf("Enter the element to be inserted: ");
scanf("%d",&data);
if(temp == NULL)
{
pointer -> data = data;
pointer -> next = NULL;
temp = pointer;
}
else
{
pointer -> data = data;
pointer -> next = temp;
temp = pointer;
}
}
}
void pop()
{
int item;
struct node *pointer;
if (temp == NULL)
{
printf("Stack Underflown");
}
else
{
41. Application of Stack in C:
The principle LIFO followed by stacks gives birth to the various applications of stacks. Some
of the most popular applications of stacks are:
1. Number reversal: A stack helps you reverse a number or a word entered as a sequence of
digits or characters respectively.
2.Undo operation: Implementation of a stack helps you perform the “undo” operation in text
editors or word processors. Here, all the changes done in the text editor are stored in a stack.
3.Infix to postfix conversion: Using stacks, you can perform the conversion of an infix
expression to a postfix expression.
4.Backtracking: Stacks are finding applications in puzzle or maze problem-solving.
5.Depth-first search (DFS): Stacks allow you to perform a searching algorithm called the
depth-first search.
Queue using linked list in C:
42. Linked List Implementation of Queue in C
As we already discussed, linked lists support the dynamic memory allocation of the data
elements of the queue. Therefore, the size of the queue is allocated during the program run and
needn’t be specified beforehand.
The 3 basic operations of Insertion, Deletion, and Display follow a similar trend as we saw in
the array implementation of queues.
It is important to note that the condition of queue overflow does not exist in the linked list
implementation of queues and the size of the stack is not pre-determined. But, the queue
underflow condition still holds true.
Insertion
This is how we can insert elements into the queue:
void insert()
{
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
43. printf("Enter the element to be inserted in the queue: ");
scanf("%d", &temp->data);
temp->link = NULL;
if (rear == NULL)
{
front = rear = temp;
}
else
{
rear->link = temp;
rear = temp;
}
}
Deletion
This is how the deletion is done in a queue:
void delet()
{
struct node *temp;
temp = front;
if (front == NULL)
{
printf("Queue underflown");
front = rear = NULL;
}
else
{
printf("The deleted element from the queue is: %dn", front->data);
front = front->link;
free(temp);
44. }
}
Display
This is how we display the elements in the queue
void display()
{
struct node *temp;
temp = front;
int cnt = 0;
if (front == NULL)
{
printf("Queue underflown");
}
else
{
printf("The elements of the stack are:n");
while (temp)
{
printf("%dn", temp->data);
temp = temp->link;
cnt++;
}
}
}
Here is a code in C that illustrates the linked list implementation of queues in C:
#include <stdio.h>
#include <stdlib.h>
45. struct node
{
int data;
struct node *link;
}*front, *rear;
void insert(); // Function used to insert the element into the queue
void delet(); // Function used to delete the elememt from the queue
void display(); // Function used to display all the elements in the queue according to FIFO rule
int main()
{
printf("Welcome to DataFlair tutorials!nn");
int choice;
printf ("LINKED LIST IMPLEMENTATION OF QUEUESnn");
do
{
printf("1. Insertn2. Deleten3. Displayn4. Exitnn");
printf("Enter your choice:");
scanf("%d",&choice);
switch(choice)
{
case 1:
insert();
break;
case 2:
46. delet();
break;
case 3:
display();
break;
case 4:
exit(0);
break;
default:
printf("Sorry, invalid choice!n");
break;
}
} while(choice!=4);
return 0;
}
void insert()
{
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
printf("Enter the element to be inserted in the queue: ");
scanf("%d", &temp->data);
temp->link = NULL;
if (rear == NULL)
{
front = rear = temp;
}
else
{
47. rear->link = temp;
rear = temp;
}
}
void delet()
{
struct node *temp;
temp = front;
if (front == NULL)
{
printf("Queue underflown");
front = rear = NULL;
}
else
{
printf("The deleted element from the queue is: %dn", front->data);
front = front->link;
free(temp);
}
}
void display()
{
struct node *temp;
temp = front;
int cnt = 0;
if (front == NULL)
{
printf("Queue underflown");
50. Linked List Operations: Traverse, Insert and Delete
There are various linked list operations that allow us to perform different actions on linked
lists. For example, the insertion operation adds a new element to the linked list.
Here's a list of basic linked list operations that we will cover in this article.
Traversal - access each element of the linked list
Insertion - adds a new element to the linked list
Deletion - removes the existing elements
Search - find a node in the linked list
Sort - sort the nodes of the linked list
Things to Remember about Linked List
head points to the first node of the linked list
next pointer of the last node is NULL, so if the next current node is NULL, we have reached
the end of the linked list.
In all of the examples, we will assume that the linked list has three nodes 1 --->2 --->3 with
node structure as below:
struct node {
int data;
struct node *next;
};
Traverse a Linked List
Displaying the contents of a linked list is very simple. We keep moving the temp node to the
next one and display its contents.
When temp is NULL, we know that we have reached the end of the linked list so we get out of
the while loop.
struct node *temp = head;
printf("nnList elements are - n");
while(temp != NULL) {
printf("%d --->",temp->data);
temp = temp->next;
51. }
The output of this program will be:
List elements are -
1 --->2 --->3 --->
Insert Elements to a Linked List:
You can add elements to either the beginning, middle or end of the linked list.
1. Insert at the beginning
Allocate memory for new node
Store data
Change next of new node to point to head
Change head to point to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = head;
head = newNode;
2. Insert at the End
Allocate memory for new node
Store data
Traverse to last node
Change next of last node to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = NULL;
struct node *temp = head;
while(temp->next != NULL){
temp = temp->next;
52. }
temp->next = newNode;
3. Insert at the Middle
Allocate memory and store data for new node
Traverse to node just before the required position of new node
Change next pointers to include new node in between
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
struct node *temp = head;
for(int i=2; i < position; i++) {
if(temp->next != NULL) {
temp = temp->next;
}
}
newNode->next = temp->next;
temp->next = newNode;
Delete from a Linked List
You can delete either from the beginning, end or from a particular position.
1. Delete from beginning
Point head to the second node
head = head->next;
2. Delete from end
Traverse to second last element
Change its next pointer to null
53. struct node* temp = head;
while(temp->next->next!=NULL){
temp = temp->next;
}
temp->next = NULL;
3. Delete from middle
Traverse to element before the element to be deleted
Change next pointers to exclude the node from the chain
for(int i=2; i< position; i++) {
if(temp->next!=NULL) {
temp = temp->next;
}
}
temp->next = temp->next->next;
Search an Element on a Linked List
You can search an element on a linked list using a loop using the following steps. We are
finding item on a linked list.
Make head as the current node.
Run a loop until the current node is NULL because the last element points to NULL.
In each iteration, check if the key of the node is equal to item. If it the key matches the item,
return true otherwise return false.
// Search a node
bool searchNode(struct Node** head_ref, int key) {
struct Node* current = *head_ref;
while (current != NULL) {
if (current->data == key) return true;
current = current->next;
54. }
return false;
}
Sort Elements of a Linked List
We will use a simple sorting algorithm, Bubble Sort, to sort the elements of a linked list in
ascending order below.
Make the head as the current node and create another node index for later use.
If head is null, return.
Else, run a loop till the last node (i.e. NULL).
In each iteration, follow the following step 5-6.
Store the next node of current in index.
Check if the data of the current node is greater than the next node. If it is greater,
swap current and index.
Check the article on bubble sort for better understanding of its working.
// Sort the linked list
void sortLinkedList(struct Node** head_ref) {
struct Node *current = *head_ref, *index = NULL;
int temp;
if (head_ref == NULL) {
return;
} else {
while (current != NULL) {
// index points to the node next to current
index = current->next;
while (index != NULL) {
if (current->data > index->data) {
temp = current->data;
current->data = index->data;
55. index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
Linked list Operations:
// Linked list operations in C
#include <stdio.h>
#include <stdlib.h>
// Create a node
struct Node {
int data;
struct Node* next;
};
// Insert at the beginning
void insertAtBeginning(struct Node** head_ref, int new_data) {
// Allocate memory to a node
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
// insert the data
new_node->data = new_data;
56. new_node->next = (*head_ref);
// Move head to new node
(*head_ref) = new_node;
}
// Insert a node after a node
void insertAfter(struct Node* prev_node, int new_data) {
if (prev_node == NULL) {
printf("the given previous node cannot be NULL");
return;
}
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = prev_node->next;
prev_node->next = new_node;
}
// Insert the the end
void insertAtEnd(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *head_ref; /* used in step 5*/
new_node->data = new_data;
new_node->next = NULL;
if (*head_ref == NULL) {
*head_ref = new_node;
57. return;
}
while (last->next != NULL) last = last->next;
last->next = new_node;
return;
}
// Delete a node
void deleteNode(struct Node** head_ref, int key) {
struct Node *temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next;
free(temp);
return;
}
// Find the key to be deleted
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
// If the key is not present
if (temp == NULL) return;
// Remove the node
prev->next = temp->next;
58. free(temp);
}
// Search a node
int searchNode(struct Node** head_ref, int key) {
struct Node* current = *head_ref;
while (current != NULL) {
if (current->data == key) return 1;
current = current->next;
}
return 0;
}
// Sort the linked list
void sortLinkedList(struct Node** head_ref) {
struct Node *current = *head_ref, *index = NULL;
int temp;
if (head_ref == NULL) {
return;
} else {
while (current != NULL) {
// index points to the node next to current
index = current->next;
while (index != NULL) {
if (current->data > index->data) {
temp = current->data;
current->data = index->data;
59. index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
// Print the linked list
void printList(struct Node* node) {
while (node != NULL) {
printf(" %d ", node->data);
node = node->next;
}
}
// Driver program
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 1);
insertAtBeginning(&head, 2);
insertAtBeginning(&head, 3);
insertAtEnd(&head, 4);
insertAfter(head->next, 5);
printf("Linked list: ");
printList(head);
60. printf("nAfter deleting an element: ");
deleteNode(&head, 3);
printList(head);
int item_to_find = 3;
if (searchNode(&head, item_to_find)) {
printf("n%d is found", item_to_find);
} else {
printf("n%d is not found", item_to_find);
}
sortLinkedList(&head);
printf("nSorted List: ");
printList(head);
}
Non integer and Non homogeneous Lists
Homogenous data structures consist of the same data element type, like element collections
found in an array. In non-homogenous structures, the data don’t have to be the same type, such
as structures.
In C, lists are not a built-in data structure like in some other programming languages such as
Python. However, you can use arrays to store a collection of elements, and these elements can
be of various data types, including non-integer types. Arrays in C can hold elements of any data
type, including floating-point numbers, characters, and other non-integer types.
Here's an example of an array in C that can hold non-integer elements:
#include <stdio.h>
int main() {
// Array of floating-point numbers
float floatArray[] = {1.5, 2.3, 3.7, 4.2, 5.1};
61. // Array of characters
char charArray[] = {'a', 'b', 'c', 'd', 'e'};
// Displaying elements of the floatArray
printf("Float Array: ");
for (int i = 0; i < sizeof(floatArray) / sizeof(floatArray[0]); i++) {
printf("%.2f ", floatArray[i]);
}
printf("n");
// Displaying elements of the charArray
printf("Char Array: ");
for (int i = 0; i < sizeof(charArray) / sizeof(charArray[0]); i++) {
printf("%c ", charArray[i]);
}
printf("n");
return 0;
}
In this example, floatArray is an array of floating-point numbers, and charArray is an array of
characters. You can create arrays for other non-integer data types as needed. Note that you need
to use the appropriate format specifier (%f for floating-point numbers, %c for characters, etc.)
when working with non-integer types in functions like printf and scanf.
In C, you typically use arrays to create homogeneous collections, meaning that all elements of
the array have the same data type. However, if you want to create a non-homogeneous
collection (a list where elements can have different data types), you may need to use a different
approach, such as structs or unions.
Here's an example using structs to create a list of elements with different data types:
#include <stdio.h>
62. // Define a struct to represent elements with different data types
struct Element {
int type; // Type identifier (e.g., 1 for int, 2 for float, 3 for char)
union {
int intValue;
float floatValue;
char charValue;
};
};
int main() {
// Create an array of struct Element to represent a non-homogeneous list
struct Element myList[] = {
{1, {42}}, // Type 1 (int)
{2, {3.14}}, // Type 2 (float)
{3, {'A'}} // Type 3 (char)
};
// Display elements of the non-homogeneous list
for (int i = 0; i < sizeof(myList) / sizeof(myList[0]); i++) {
switch (myList[i].type) {
case 1:
printf("Element %d: %d (Type: int)n", i + 1, myList[i].intValue);
break;
case 2:
printf("Element %d: %.2f (Type: float)n", i + 1, myList[i].floatValue);
break;
case 3:
printf("Element %d: %c (Type: char)n", i + 1, myList[i].charValue);
63. break;
default:
printf("Unknown typen");
}
}
return 0;
}
In this example, the Element struct has a field type to identify the type of the data stored in the
union. The union allows you to store different types of data in the same memory location. The
main function demonstrates how to create a non-homogeneous list using an array of these
structs.
Keep in mind that managing a non-homogeneous list in C can be more complex than using a
language with built-in support for such structures (like Python or JavaScript).
Top of Form
Comparing the Dynamic and Array Implementations of Lists
64. Implementing Header Nodes in linked list.
In a linked list, header nodes are often used to simplify operations and improve the efficiency
of certain operations, such as insertion and deletion. A header node is a special node that sits
at the beginning of the linked list and does not store any data. Its purpose is to serve as a
placeholder, making it easier to handle edge cases and simplifying the implementation of
various operations.
#include <stdio.h>
#include <stdlib.h>
// Define the structure for a node
65. struct Node {
int data;
struct Node* next;
};
// Define the linked list with a header node
struct HeaderLinkedList {
struct Node* header;
};
// Function to initialize the linked list with a header node
void initializeList(struct HeaderLinkedList* list) {
list->header = (struct Node*)malloc(sizeof(struct Node));
list->header->next = NULL;
}
// Function to check if the linked list is empty
int isEmpty(struct HeaderLinkedList* list) {
return list->header->next == NULL;
}
// Function to insert a new node at the beginning of the linked list
void insertAtBeginning(struct HeaderLinkedList* list, int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = list->header->next;
list->header->next = newNode;
}
66. // Function to display the linked list
void display(struct HeaderLinkedList* list)
{
struct Node* current = list->header->next;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULLn");
}
// Function to free the memory allocated for the linked list
void freeList(struct HeaderLinkedList* list)
{
struct Node* current = list->header;
while (current != NULL)
{
struct Node* next = current->next;
free(current);
current = next;
}
}
int main()
{
// Create a linked list with a header node
struct HeaderLinkedList linkedList;
initializeList(&linkedList);
// Check if the linked list is empty
67. printf("Is the linked list empty? %sn", isEmpty(&linkedList) ? "Yes" : "No");
// Insert elements at the beginning
insertAtBeginning(&linkedList, 3);
insertAtBeginning(&linkedList, 2);
insertAtBeginning(&linkedList, 1);
// Display the linked list
printf("Linked List: ");
display(&linkedList);
// Free the memory allocated for the linked list
freeList(&linkedList);
return 0;
}
This C program demonstrates the implementation of a linked list with a header node. The
initializeList, isEmpty, insertAtBeginning, display, and freeList functions are used for various
operations on the linked list.