0% found this document useful (0 votes)
17 views

DSA2

Uploaded by

tashiki
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

DSA2

Uploaded by

tashiki
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 150

Linked List

Definition:
A linked list is a linear data structure, in which the elements are not stored
at contiguous memory locations. inked List can be defined as collection of
objects called nodes that are randomly stored in the memory.
A node contains two fields i.e. data stored at that particular address and
the pointer which contains the address of the next node in the memory.
The last node of the list contains pointer to the null.

Representation of a Linked list and Memory Allocation:

Linked list can be represented as the connection of nodes in which each


node points to the next node of the list.
the group of elements that are to be stored individually in the memory.
The linked list uses the dynamic memory allocation method.
In this method, a linked list data structure is used to distribute memory.
Memory is divided into a number of blocks of similar size when allocating
a linked list.
Garbage Collection in Data Structure:
Garbage Collector:

Garbage collection (GC) is a dynamic technique for memory


management and heap allocation
the garbage collector identifies the used and unused chunks of memory.
The garbage collector is used to manage the memory, and it is a program
written in Java.
the most famous and commonly implemented Garbage Collection
techniques.
1. Mark and Sweep
2. Reference Counting

Mark and Sweep:

Garbage Collector works in two phases, i.e., Mark and Sweep.


Mark is an area where the garbage collector identifies the used and
unused chunks of memory.
The Sweep removes the identified object from the Mark
Reference Counting:

Reference counting garbage collection is where each object has a count of


the number of references to it.
Garbage is identified by having a reference count of zero.
An object's reference count is incremented when a reference to it is
created, and decremented when a reference is destroyed.
Types of Linked List:

A linked list is a linear data structure, in which the elements are not stored
at contiguous memory locations. inked List can be defined as collection of
objects called nodes that are randomly stored in the memory.
A node contains two fields i.e., data stored at that particular address and
the pointer which contains the address of the next node in the memory.
The last node of the list contains pointer to the null.
The linked list classifieds into 3 types
1. Singly Linked List
2. Doubly Linked List
3. Circular Linked List
A. Circular Singly Linked List
B. Circular Doubly Linked List.
Singly Linked List:

The singly linked list is a data structure that contains two parts, i.e., one is
the data part, and the other one is the address part,
which contains the address of the next or the successor node.
The address part in a node is also known as a pointer.
The data part is used to store the Data and Address/ next link part is used
to connect with next successor Node.

Syntax:
struct node
{
int data;
struct node *next;
}
Doubly linked list:

As the name suggests, the doubly linked list contains two pointers.
We can define the doubly linked list as a linear data structure with three
parts:
the data part and the other two address part.
a doubly linked list is a list that has three parts,
one data part, a pointer to its previous node, and a pointer to the next
node.

struct node
{
struct node *prev;
int data;
struct node *next;
}
Circular Linked List:

Circular Linked List is a variation of Linked list in which the first


element points to the last element.

the last element points to the first element.

Both Singly Linked List and Doubly Linked List can be made into a
circular linked list.

Circular singly linked list:

In a circular Singly linked list, the last node of the list contains a pointer
to the first node of the list.

We traverse the circular singly linked list until we reach the same node
where we started.

The circular singly linked list has no beginning or end.


Circular Doubly Linked List:

A circular doubly linked list is a mixture of a doubly linked list and a


circular linked list.
the doubly linked list, it has an extra pointer called the previous pointer,
and similar to the circular linked list, its last node points at the head node.
Example: Linked list implementation in C:

#include <stdio.h>
#include <stdlib.h>
struct node // Creating a node
{
int value;
struct node *next;
};
void printLinkedlist(struct node *p) // print the linked list value
{
while (p != NULL)
{
printf("%d ", p->value);
p = p->next;
}
}
int main()
{
struct node *head; // Initialize nodes
struct node *Node1 = NULL;
struct node *Node2 = NULL;
struct node *Node3 = NULL;
Node1 = malloc(sizeof(struct node)); // Allocate memory
Node2 = malloc(sizeof(struct node));
Node3 = malloc(sizeof(struct node));
Node1->value = 10; // Assign value values
Node2->value = 20;
Node3->value = 30;
Node1->next = Node2; // Connect nodes
Node2->next = Node3;
Node3->next = NULL;
head = Node1; // printing node-value
printLinkedlist(head);
}

Output:
10 20 30
Operations in the Singly Linked Lists:

The basic operations in the linked lists are insertion, deletion, searching, display,
and deleting an element at a given key. These operations are performed on
Singly Linked Lists.
Insertion: − Adds an element at the beginning of the list.
Deletion: − Deletes an element at the beginning of the list.
Display: − Displays the complete list.
Search: − Searches an element using the given key.
Delete: − Deletes an element using the given key.

Insertion at Begin:
In this operation, we are adding an element at the
beginning of the list.

Step1: insert the Node into the Singly Linked List at Begin

40
Example: Insertion at Begin:

Algorithm:

Algorithm to insert node at the beginning of Singly Linked List

Begin:

createSinglyLinkedList (head)

alloc (newNode)

If (newNode == NULL) then

write ('Unable to allocate memory')

End if

Else then

read (data)wo

newNode.data ← data

newNode.next ← head

head ← newNode

End else

End
Example:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

struct node

int data;

struct node *next;

};

struct node *head = NULL;

struct node *current = NULL;

void printList() // display the list

struct node *p = head;

printf("\n[");

while(p != NULL) //start from the beginning

printf(" %d ",p->data);

p = p->next;

printf("]");

}
void insertatbegin(int data) //insertion at the beginning

struct node *link = (struct node*) malloc(sizeof(struct node));

link ->data = data; //create a link

link ->next = head; // point it to old first node

head = link; //point first to new first node

void main()

int k=0;

insertatbegin(12);

insertatbegin(22);

insertatbegin(30);

insertatbegin(44);

insertatbegin(50);

printf("Linked List: ");

printList(); // print list

Output:

Linked List:

[ 50 44 30 22 12 ]
Insertion at Middle Position:

Step2: insert the Node at Middle position or intermediate position


Algorithm to insert node at the middle of Singly Linked List
%% Input : n position to insert data in the list

createSinglyLinkedList (head)
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory.')
End if
Else then
read (data)
newNode.data ← data
temp ← head
For i ← 2 to n-1
temp ← temp.next
If (temp == NULL) then
break
End if
End for
If (temp != NULL) then
newNode.next ← temp.next
temp.next ← newNode
End if
End else
End
Example:
#include <stdio.h>
struct node //Represent a node of the singly linked list
{
int data;
struct node *next;
};
int size;
//Represent the head and tail of the singly linked list
struct node *head, *tail = NULL;
void addNode(int data) //addNode() will add a new node to the list
{
//Create a new node
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if(head = = NULL) //Checks if the list is empty
{
head = newNode; //If list is empty, both head and tail will point to new node
tail = newNode;
}
else
{
//newNode will be added after tail such that tail's next will point to newNode
tail->next = newNode;
tail = newNode; //newNode will become new tail of the list
}
size++; //Size will count the number of nodes present in the list
}
//This function will add the new node at the middle of the list.
void addInMid(int data)
{
//Create a new node
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if(head == NULL) //Checks if the list is empty
{
//If list is empty, both head and tail would point to new node
head = newNode;
tail = newNode;
}
else
{
struct node *temp, *current;
//Store the mid position of the list
int count = (size % 2 == 0) ? (size/2) : ((size+1)/2);
temp = head; //Node temp will point to head
current = NULL;
//Traverse through the list till the middle of the list is reached
for(int i = 0; i < count; i++)
{
current = temp; //Node current will point to temp
temp = temp->next; //Node temp will point to node next to it.
}
current->next = newNode; //current will point to new node
newNode->next = temp; //new node will point to temp
}
size++;
}
void display() //display() will display all the nodes present in the list
{
struct node *current = head; //Node current will point to head
if(head == NULL)
{
printf(" List is empty\n ");
return;
}
while(current != NULL)
{
printf("%d ", current->data); //Prints each node by incrementing pointer
current = current->next;
}
printf("\n");
}
int main()
{
addNode(10); //Adds data to the list
addNode(20);
printf(" Original list: \n ");
display();
addInMid(30); //Inserting node '3' in the middle
printf( " Updated List: \n ");
display();
addInMid(40); //Inserting node '3' in the middle
printf( " Updated List: \n ");
display();
return 0;
}

Output:
Original list:
10 20
Updated List:
10 30 20
Updated List:
10 30 40 20
Insertion at Ending:

In this operation, we are adding an element at the ending of the list.


insert the Node at End position or Last position
Algorithm
Algorithm to insert node at the end of a Singly Linked List:
Begin:
createSinglyLinkedList (head)
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
newNode.data ← data
newNode.next ← NULL
temp ← head
While (temp.next != NULL) do
temp ← temp.next
End while
temp.next ← newNode
End else
End
Example:

#include <stdio.h>
#include <stdlib.h>
struct node /* Structure of a node */
{
int data; // Data
struct node *next; // Address
}
*head;
void createList(int n);
void insertNodeAtEnd(int data);
void displayList();
int main()
{
int n, data;
printf(" Enter the total number of nodes: ");//Create a singly linked list of n nodes
scanf("%d", &n);
createList(n);
printf(" \n Data in the list \n ");
displayList();
printf(" \n Enter data to insert at end of the list: ");//Insert data at the end of the singly
linked list
scanf("%d", &data);
insertNodeAtEnd(data);
printf(" \n Data in the list \n ");
displayList();
return 0;
}
void createList(int n) //Create a list of n nodes
{
struct node *newNode, *temp;
int data, i;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL) // If unable to allocate memory for head node
{
printf(" Unable to allocate memory.");
}
else
{
printf("Enter the data of node 1: ");//Reads data of node from the user
scanf("%d", &data);
head->data = data; // Link the data field with data
head->next = NULL; // Link the address field to NULL
temp = head;
for(i=2; i<=n; i++) //Create n nodes and adds to linked list
{
newNode = (struct node *) malloc (sizeof(struct node));
if(newNode == NULL) /* If memory is not allocated for newNode */
{
printf(" Unable to allocate memory.");
break;
}
else
{
printf("Enter the data of node %d: ", i);
scanf("%d", &data);
newNode->data = data; // Link the data field of newNode with data
newNode->next = NULL; // Link the address field of newNode with NULL
temp->next = newNode; // Link previous node i.e. temp to the newNode
temp = temp->next;
}
}
printf("SINGLY LINKED LIST CREATED SUCCESSFULLY\n");
}
}
//Create a new node and inserts at the end of the linked list.
void insertNodeAtEnd(int data)
{
struct node *newNode, *temp;
newNode = (struct node*)malloc(sizeof(struct node));
if(newNode == NULL)
{
printf(" Unable to allocate memory.");
}
else
{
newNode->data = data; // Link the data part
newNode->next = NULL;
temp = head;
while(temp != NULL && temp->next != NULL) // Traverse to the last node
temp = temp->next;
temp->next = newNode; // Link address part
printf(" DATA INSERTED SUCCESSFULLY \n");
}

}
void displayList() //Display entire list
{
struct node *temp;
if(head == NULL) //If the list is empty i.e. head = NULL
{
printf("List is empty.");
}
else
{
temp = head;
while(temp != NULL)
{
printf("Data = %d\n", temp->data); // Print data of current node
temp = temp->next; // Move to next node
}
}
}

Output:

Enter the total number of nodes: 3


Enter the data of node 1: 10
Enter the data of node 2: 20
Enter the data of node 3: 30
SINGLY LINKED LIST CREATED SUCCESSFULLY

Data in the list


Data = 10
Data = 20
Data = 30
Enter data to insert at end of the list: 50
DATA INSERTED SUCCESSFULLY
Data in the list
Data = 10
Data = 20
Data = 30
Data = 50
Delete first node of Singly Linked List:
Deleting a node from the beginning of the list is the simplest operation of
all.
It just needs a few adjustments in the node pointers.
Since the first node of the list is to be deleted, therefore, we just need to
make the head, point to the next of the head.
Algorithm to delete first node from Singly Linked List

Algorithm to delete first node of Singly Linked List

%%Input: head of the linked list

Begin:

If (head != NULL) then

toDelete ← head

head ← head.next

unalloc (toDelete)

End if

End
Example:

#include <stdio.h>
#include <stdlib.h>
struct node /* Structure of a node */
{
int data; // Data
struct node *next; // Address
}
*head;
void createList(int n);
void deleteFirstNode();
void displayList();
int main()
{
int n, choice;
printf("Enter the total number of nodes: ");//Create a singly linked list of n nodes
scanf("%d", &n);
createList(n);
printf(" \n Data in the list \n");
displayList();
printf(" \n Press 1 to delete first node: ");
scanf("%d", &choice);
if(choice == 1) /* Delete first node from list */
deleteFirstNode();
printf(" \n Data in the list \n");
displayList();
return 0;
}
void createList(int n) //Create a list of n nodes
{
struct node *newNode, *temp;
int data, i;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL) //If unable to allocate memory for head node
{
printf("Unable to allocate memory.");
}
else
{
printf("Enter the data of node 1: "); //In data of node from the user
scanf("%d", &data);
head->data = data; // Link the data field with data
head->next = NULL; // Link the address field to NULL
temp = head;
for(i=2; i<=n; i++) //Create n nodes and adds to linked list
{
newNode = (struct node *) malloc (sizeof(struct node));
if(newNode == NULL) /* If memory is not allocated for newNode */
{
printf("Unable to allocate memory.");
break;
}
else
{
printf("Enter the data of node %d: ", i);
scanf("%d", &data);
newNode->data = data; // Link the data field of newNode with data
newNode->next = NULL; // Link the address field of newNode with NULL
temp->next = newNode; // Link previous node i.e. temp to the newNode
temp = temp->next;
}
}
printf("SINGLY LINKED LIST CREATED SUCCESSFULLY \n");
}
}
void deleteFirstNode() //Deletes the first node of the linked list
{
struct node *toDelete;
if(head == NULL)
{
printf("List is already empty.");
}
else
{
toDelete = head;
head = head->next;
printf(" \n Data deleted = %d\n", toDelete->data);
free(toDelete); /* Clears the memory occupied by first node*/
printf("SUCCESSFULLY DELETED FIRST NODE FROM LIST \n");
}
}
void displayList() //Displays the entire list
{
struct node *temp;
if(head == NULL) //If the list is empty i.e. head = NULL
{
printf("List is empty.");
}
else
{
temp = head;
while(temp != NULL)
{
printf("Data = %d\n", temp->data); // Print data of current node
temp = temp->next; // Move to next node
}
}
}

Output:

Enter the total number of nodes: 3


Enter the data of node 1: 10
Enter the data of node 2: 20
Enter the data of node 3: 30
SINGLY LINKED LIST CREATED SUCCESSFULLY
Data in the list
Data = 10
Data = 20
Data = 30
Press 1 to delete first node: 1
Data deleted = 10
SUCCESSFULLY DELETED FIRST NODE FROM LIST
Data in the list
Data = 20
Data = 30
Delete a node from the middle of the singly linked list:

In this program, we will create a singly linked list and delete a node from
the middle of the list.
To accomplish this task, we will calculate the size of the list and then
divide it by 2 to get the mid-point of the list.
Node temp will point to head node. We will iterate through the list till
midpoint is reached. Now, the temp will point to middle node and node
current will point to node previous to temp.
We delete the middle node such that current's next node will point to
temp's next node.
Algorithm to delete middle node of Singly Linked List:
%%Input: head node of the linked list
n node to be deleted
Begin:
If (head == NULL) then
write ('List is already empty')
End if
Else then
toDelete ← head
prevNode ← head
For i←2 to n do
prevNode ← toDelete
toDelete ← toDelete.next
If (toDelete == NULL) then
break
End if
End for
If (toDelete != NULL) then
If (toDelete == head) then
head ← head.next
End if
prevNode.next ← toDelete.next
toDelete.next ← NULL
unalloc (toDelete)
End if
End else
End
Example:

#include <stdio.h>
#include <stdlib.h>
struct node /* Structure of a node */
{
int data; // Data
struct node *next; // Address
} *head;
void createList(int n); /* Functions used in program */
void deleteMiddleNode(int position);
void displayList();
int main()
{
int n, position;
printf(" Enter the total number of nodes: ");//Create a singly linked list of n
nodes
scanf("%d", &n);
createList(n);
printf(" \n Data in the list \n ");
displayList();
printf(" \n Enter the node position you want to delete: ");
scanf("%d", &position);
deleteMiddleNode(position); /* Delete middle node from list */
printf(" \n Data in the list \n ");
displayList();
return 0;
}
void createList(int n) //Create a list of n nodes
{
struct node *newNode, *temp;
int data, i;
head = (struct node *) malloc (sizeof(struct node));
if(head == NULL) //If unable to allocate memory for head node
{
printf(" Unable to allocate memory.");
}
else
{
printf("Enter the data of node 1: "); //Read data of node from the user
scanf("%d", &data);
head->data = data; // Link the data field with data
head->next = NULL; // Link the address field to NULL
temp = head;
for(i=2; i<=n; i++) //Create n nodes and adds to linked list
{
newNode = (struct node *) malloc (sizeof(struct node));
if(newNode == NULL) /* If memory is not allocated for newNode */
{
printf(" Unable to allocate memory.");
break;
}
else
{
printf(" Enter the data of node %d: ", i);
scanf("%d", &data);
newNode->data = data; // Link the data field of newNode with data
newNode->next = NULL; // Link the address field of newNode with NULL
temp->next = newNode; // Link previous node i.e. temp to the newNode
temp = temp->next;
}
}
printf("SINGLY LINKED LIST CREATED SUCCESSFULLY\n");
}
}
void deleteMiddleNode(int position) //Delete middle node of the linked list
{
int i;
struct node *toDelete, *prevNode;
if(head == NULL)
{
printf("List is already empty.");
}
else
{
toDelete = head;
prevNode = head;
for(i=2; i<=position; i++)
{
prevNode = toDelete;
toDelete = toDelete->next;
if(toDelete == NULL)
break;
}
if(toDelete != NULL)
{
if(toDelete == head)
head = head->next;
prevNode->next = toDelete->next;
toDelete->next = NULL;
free(toDelete); /* Delete nth node */
printf("SUCCESSFULLY DELETED NODE FROM MIDDLE OF LIST \n");
}
else
{
printf("Invalid position unable to delete.");
}
}
}
void displayList() //Display entire list
{
struct node *temp;
if(head == NULL) //If the list is empty i.e. head = NULL
{
printf("List is empty.");
}
else
{
temp = head;
while(temp != NULL)
{
printf("Data = %d\n", temp->data); // Print the data of current node
temp = temp->next; // Move to next node
}
}
}

Output:

Enter the total number of nodes: 3

Enter the data of node 1: 100

Enter the data of node 2: 200

Enter the data of node 3: 300

SINGLY LINKED LIST CREATED SUCCESSFULLY

Data in the list

Data = 100

Data = 200

Data = 300

Enter the node position you want to delete: 2

SUCCESSFULLY DELETED NODE FROM MIDDLE OF LIST

Data in the list

Data = 100

Data = 300
Delete a node from the End/Last of the singly linked list:

In this program, we will create a singly linked list and delete a node from
the end of the list.
To accomplish this task, we first find out the second last node of the list.
Then, make second last node as the new tail of the list.
Then, delete the last node of the list.
Algorithm to delete last node of Singly Linked List:
%%Input: head node of the linked list
Begin:
If (head == NULL) then
write ('List is already empty')
End if
Else then
toDelete ← head
secondLastNode ← head
While (toDelete.next != NULL) do
secondLastNode ← toDelete
toDelete ← toDelete.next
End while
If (toDelete == head) then
head ← NULL
End if
Else then
secondLastNode.next ← NULL
End else
unalloc (toDelete)
End else
End
Example:

#include <stdio.h>
#include <stdlib.h>
struct node /* Structure of a node */
{
int data; // Data
struct node *next; // Address
}*head;
void createList(int n);
void deleteLastNode();
void displayList();
int main()
{
int n, choice;
printf("Enter the total number of nodes: ");//Create a singly linked list of n
nodes
scanf("%d", &n);
createList(n);
printf(" \n Data in the list \n");
displayList();
printf(" \n Press 1 to delete last node: ");
scanf("%d", &choice);
if(choice == 1) /* Delete last node from list */
deleteLastNode();
printf(" \n Data in the list \n");
displayList();
return 0;
}
void createList(int n) //Create a list of n nodes
{
struct node *newNode, *temp;
int data, i;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL) //If unable to allocate memory for head node
{
printf("Unable to allocate memory.");
}
else
{
printf("Enter the data of node 1: "); //Input data of node from the user
scanf("%d", &data);
head->data = data; // Link the data field with data
head->next = NULL; // Link the address field to NULL
temp = head;
for(i=2; i<=n; i++) //Create n nodes and adds to linked list
{
newNode = (struct node *)malloc(sizeof(struct node));
if(newNode == NULL) /* If memory is not allocated for newNode */
{
printf("Unable to allocate memory.");
break;
}
else
{
printf("Enter the data of node %d: ", i);
scanf("%d", &data);
newNode->data = data; // Link the data field of newNode with data
newNode->next = NULL; // Link the address field of newNode with NULL
temp->next = newNode; // Link previous node i.e. temp to the newNode
temp = temp->next;
}
}
printf("SINGLY LINKED LIST CREATED SUCCESSFULLY\n");
}
}
void deleteLastNode() //Delete last node of the linked list
{
struct node *toDelete, *secondLastNode;
if(head == NULL)
{
printf("List is already empty.");
}
else
{
toDelete = head;
secondLastNode = head;
while(toDelete->next != NULL) /* Traverse to the last node of the list */
{
secondLastNode = toDelete;
toDelete = toDelete->next;
}
if(toDelete == head)
{
head = NULL;
}
else
{
/* Disconnect link of second last node with last node */
secondLastNode->next = NULL;
}
free(toDelete); /* Delete the last node */
printf("SUCCESSFULLY DELETED LAST NODE OF LIST\n");
}
}
void displayList()//Display entire list
{
struct node *temp;
if(head == NULL) //If the list is empty i.e. head = NULL
{
printf("List is empty.");
}
else
{
temp = head;
while(temp != NULL)
{
printf("Data = %d \n", temp->data); // Print the data of current node
temp = temp->next; // Move to next node
}
}
}

Output:

Enter the total number of nodes: 3


Enter the data of node 1: 10
Enter the data of node 2: 20
Enter the data of node 3: 30
SINGLY LINKED LIST CREATED SUCCESSFULLY

Data in the list


Data = 10
Data = 20
Data = 30

Press 1 to delete last node: 1


SUCCESSFULLY DELETED LAST NODE OF LIST

Data in the list


Data = 10
Data = 20
Doubly Linked List: Operations:

Doubly linked list:

The doubly linked list contains two pointers.


We can define the doubly linked list as a linear data structure with three
parts:
the data part and the other two address part.
a doubly linked list is a list that has three parts,
one data part, a pointer to its previous node, and a pointer to the next
node.

Operations:

Following are the basic operations supported by a list.

Insertion − Adds an element at the beginning of the list.


Insertion − Adds an element at the middle of the list
Insert Last − Adds an element at the end of the list.
Deletion − Deletes an element at the beginning of the list.
Deletion − Deletes an element at the middle of the list.
Delete Last − Deletes an element from the end of the list.
Insert After − Adds an element after an item of the list.

Delete − Deletes an element from the list using the key.


insert node at the Beginning of a Doubly linked list

In doubly linked list, each node of the list contains double pointers,
therefore, we have to maintain more number of pointers in doubly linked
list as compare to singly linked list.
There are two scenarios of inserting any element into doubly linked list.
Either the list is empty or it contains at least one element.
Perform the following steps to insert a node in doubly linked list at
beginning.
Allocate the space for the new node in the memory.
This will be done by using the following statement.

ptr = (struct node *)malloc(sizeof(struct node));

Check whether the list is empty or not. The list is empty if the condition
head == NULL holds. In that case, the node will be inserted as the only
node of the list and therefore the prev and the next pointer of the node will
point to NULL and the head pointer will point to this node.

ptr->next = NULL;
ptr->prev=NULL;
ptr->data=item;
head=ptr;
In the second scenario, the condition head == NULL become false and the
node will be inserted in beginning. The next pointer of the node will point
to the existing head pointer of the node. The prev pointer of the existing
head will point to the new node being inserted.

This will be done by using the following statements.

ptr->next = head;
head→prev=ptr;
Algorithm to insert a node at the Beginning of a Doubly linked list

Step 1: IF ptr = NULL

Write OVERFLOW
Go to Step 9
[END OF IF]

Step 2: SET NEW_NODE = ptr

Step 3: SET ptr = ptr -> NEXT

Step 4: SET NEW_NODE -> DATA = VAL

Step 5: SET NEW_NODE -> PREV = NULL

Step 6: SET NEW_NODE -> NEXT = START

Step 7: SET head -> PREV = NEW_NODE

Step 8: SET head = NEW_NODE

Step 9: EXIT
Insertion at End/Last Position:

In this operation, we are adding an element at the ending of the list.


insert the Node at End position or Last position.

Algorithm to insert a node at the end of Doubly linked list

%% Input: last {Pointer to the last node of doubly linked list}

Begin:
alloc (newNode)
If (newNode == NULL) then
write ('Unable to allocate memory')
End if
Else then
read (data)
newNode.data ← data;
newNode.next ← NULL;
newNode.prev ← last;
last.next ← newNode;
last ← newNode;
write ('Node added successfully at the end of List')
End else
End
insert node at any position:
Algorithm to insert node at any position of a Doubly linked list
Algorithm to insert node at any position of doubly linked list
%% Input : head {Pointer to the first node of doubly linked list}
: last {Pointer to the last node of doubly linked list}
: N {Position where node is to be inserted}
Begin:
temp ← head
For i←1 to N-1 do
If (temp == NULL) then
break
End if
temp ← temp.next;
End for
If (N == 1) then
insertAtBeginning()
End if
Else If (temp == last) then
insertAtEnd()
End if
Else If (temp != NULL) then
alloc (newNode)
read (data)
newNode.data ← data;
newNode.next ← temp.next
newNode.prev ← temp
If (temp.next != NULL) then
temp.next.prev ← newNode;
End if
temp.next ← newNode;
write('Node added successfully')
End if
End
Example:

#include <stdio.h>
#include <stdlib.h>
struct node //Basic structure of Node
{
int data;
struct node * prev;
struct node * next;
}*head, *last;
void createList(int n); //Function used in this program
void displayList();
void insertAtBeginning(int data);
void insertAtEnd(int data);
void insertAtN(int data, int position);
int main()
{
int n, data, choice=1;
head = NULL;
last = NULL;
while(choice != 0) //Run forever until user chooses 0
{
//Menu creation to use the program
printf("============================================\n");
printf("DOUBLY LINKED LIST PROGRAM\n");
printf("============================================\n");
printf("1. Create List\n");
printf("2. Insert node - at beginning\n");
printf("3. Insert node - at end\n");
printf("4. Insert node - at N\n");
printf("5. Display list\n");
printf("0. Exit\n");
printf("--------------------------------------------\n");
printf("Enter your choice : ");
scanf("%d", &choice);
switch(choice) //Choose from different menu operation
{
case 1:
printf("Enter the total number of nodes in list: ");
scanf("%d", &n);
createList(n);
break;
case 2:
printf("Enter data of first node : ");
scanf("%d", &data);
insertAtBeginning(data);
break;
case 3:
printf("Enter data of last node : ");
scanf("%d", &data);
insertAtEnd(data);
break;
case 4:
printf("Enter the position where you want to insert new node: ");
scanf("%d", &n);
printf("Enter data of %d node : ", n);
scanf("%d", &data);
insertAtN(data, n);
break;
case 5:
displayList();
break;
case 0:
break;
default:
printf("Error! Invalid choice. Please choose between 0-5");
}
printf(" \n \n \n \n \n");
}
return 0;
}
// Creates a doubly linked list of n nodes.
* @n Number of nodes to be created
void createList(int n)
{
int i, data;
struct node *newNode;
if(n >= 1)
{
//Create and link the head node
head = (struct node *)malloc(sizeof(struct node));
printf("Enter data of 1 node: ");
scanf("%d", &data);
head->data = data;
head->prev = NULL;
head->next = NULL;
last = head;
for(i=2; i<=n; i++) //Create and link rest of the n-1 nodes
{
newNode = (struct node *)malloc(sizeof(struct node));
printf("Enter data of %d node: ", i);
scanf("%d", &data);
newNode->data = data;
newNode->prev = last; // Link new node with the previous node
newNode->next = NULL;
last->next = newNode; // Link previous node with the new node
last = newNode; // Make new node as last/previous node
}
printf(" \n DOUBLY LINKED LIST CREATED SUCCESSFULLY\n");
}
}
void displayList() //Display content of the list from beginning to end
{
struct node * temp;
int n = 1;
if(head == NULL)
{
printf("List is empty.\n");
}
else
{
temp = head;
printf("DATA IN THE LIST:\n");
while(temp != NULL)
{
printf("DATA of %d node = %d\n", n, temp->data);
n++;
temp = temp->next; /* Move the current pointer to next node */
}
}
}
/* Inserts a new node at the beginning of the doubly linked list
* @data Data of the first node i.e. data of the new node
*/
void insertAtBeginning(int data)
{
struct node * newNode;
if(head == NULL)
{
printf("Error, List is Empty!\n");
}
else
{
newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = data;
newNode->next = head; // Point to next node which is currently head
newNode->prev = NULL; // Previous node of first node is NULL
head->prev = newNode; /* Link previous address field of head with newnode */
head = newNode; /* Make the new node as head node */
printf("NODE INSERTED SUCCESSFULLY AT THE BEGINNING OF THE LIST \n");
}
}
/*Inserts a new node at the end of the doubly linked list
@data Data of the last node i.e data of the new node*/
void insertAtEnd(int data)
{
struct node * newNode;
if(last == NULL)
{
printf("Error, List is empty!\n");
}
else
{
newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
newNode->prev = last;
last->next = newNode;
last = newNode;
printf("NODE INSERTED SUCCESSFULLY AT THE END OF LIST\n");
}
}
/**
* Inserts a node at any position in the doubly linked list
* @data Data of the new node to be inserted
* @position Position where to insert the new node
*/
void insertAtN(int data, int position)
{
int i;
struct node * newNode, *temp;
if(head == NULL)
{
printf("Error, List is empty!\n");
}
else
{
temp = head;
i=1;
while(i<position-1 && temp!=NULL)
{
temp = temp->next;
i++;
}
if(position == 1)
{
insertAtBeginning(data);
}
else if(temp == last)
{
insertAtEnd(data);
}
else if(temp!=NULL)
{
newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = data;
newNode->next = temp->next; // Connect new node with n+1th node
newNode->prev = temp; // Connect new node with n-1th node
if(temp->next != NULL)
{
temp->next->prev = newNode; /* Connect n+1th node with new node */
}
temp->next = newNode; /* Connect n-1th node with new node */
printf("NODE INSERTED SUCCESSFULLY AT %d POSITION\n", position);
}
else
{
printf("Error, Invalid position\n");
}
}
}
Output:
============================================
DOUBLY LINKED LIST PROGRAM
============================================
1. Create List
2. Insert node - at beginning
3. Insert node - at end
4. Insert node - at N
5. Display list
0. Exit
--------------------------------------------
Enter your choice: 1
Enter the total number of nodes in list: 3
Enter data of 1 node: 10
Enter data of 2 node: 20
Enter data of 3 node: 30
DOUBLY LINKED LIST CREATED SUCCESSFULLY
============================================
DOUBLY LINKED LIST PROGRAM
============================================
1. Create List
2. Insert node - at beginning
3. Insert node - at end
4. Insert node - at N
5. Display list
0. Exit
Insertion at First/ Begining Position:

Insertion − Adds an element at the beginning of the list

Algorithm:

1. START

2. Create a new node with three variables: prev, data, next.

3. Store the new data in the data variable

4. If the list is empty, make the new node as head.

5. Otherwise, link the address of the existing first node to the next variable of
the new node, and assign null to the prev variable.

6. Point the head to the new node.

7. END
Example:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <stdbool.h>

struct node

int data;

int key;

struct node *next;

struct node *prev;

};

struct node *head = NULL; //this link always point to first Link

struct node *last = NULL; //this link always point to last Link

struct node *current = NULL;

bool isEmpty() //is list empty

return head == NULL;

}
void printList() //display the doubly linked list

struct node *ptr = head;

while(ptr != NULL)

printf("(%d, %d) ",ptr->key, ptr->data);

ptr = ptr->next;

void insertFirst(int key, int data) //insert link at the first location

struct node *link = (struct node*) malloc(sizeof(struct node)); //create a link

link->key = key;

link->data = data;

if(isEmpty())

last = link; //make it the last link

else

head->prev = link; //update first prev link


}

link->next = head; //point it to old first link

head = link; //point first to new first link

void main()

insertFirst(0, 10);

insertFirst(1, 20);

insertFirst(2, 30);

insertFirst(3, 40);

insertFirst(4, 50);

insertFirst(5, 56);

printf("\n Doubly Linked List: ");

printList();

Output:

Doubly Linked List: (5, 60) (4, 50) (3, 40) (2, 30) (1, 20) (0, 10)
Insertion at Middle Position:

1. Firstly, create a new node (say new_node).


2. Now insert the data in the new node.
3. Point the next of new_node to the next of prev_node.
4. Point the next of prev_node to new_node.
5. Point the previous of new_node to prev_node.
6. Change the pointer of the new node’s previous pointer to new_node.
Example:

#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next, *prev;
};
int size = 0;
void insert (struct Node **head, int data)
{
struct Node *newNode = (struct Node *) malloc (sizeof (struct Node));
newNode->data = data;
newNode->next = *head;
newNode->prev = NULL;
if (*head != NULL) //If the linked list already had atleast 1 node
(*head)->prev = newNode;
*head = newNode; // changing the new head to this freshly entered node
size++;
}
void insertMiddle (struct Node **head, int data)
{
struct Node *newNode = (struct Node *) malloc (sizeof (struct Node));
newNode->data = data;
if (*head == NULL) // if the LL was empty
{
insert (head, data); // using insert function to insert at start
return;
}
// otherwise
// find correct insertion position for middle
int mid = (size % 2 == 0) ? (size / 2) : (size + 1) / 2;
// will only happen when there is one node in Doubly Linked List
// we will have to insert at the last,
// inserting 2nd node at the last
// Example size = 1 will result in mid = 1 so entering after 1st node
// where size itself is 1 so entering last node
if (mid == size)
{
newNode->next = NULL;
newNode->prev = *head;
(*head)->next = newNode;
size++;
return;
}
struct Node *temp = *head;
while (--mid) // traverse to current mid position
{
temp = temp->next;
}
(temp->next)->prev = newNode; // (mid+1)th node prev to this newNode
newNode->prev = temp; // newNode's prev to this current middle node
newNode->next = temp->next; // newNode's next to (mid+1)th node
temp->next = newNode; // current mid node's next becomes this newNode
size++; // this new inserted after the middle node successfully
}
void display (struct Node *node) //function to print the doubly linked list
{
printf ( "\n \n" );
struct Node *end = NULL;
printf ("List in Forward direction: ");
while (node != NULL)
{
printf (" %d ", node->data);
end = node;
node = node->next;
}
printf (" \n List in backward direction: ");
while (end != NULL)
{
printf (" %d ", end->data);
end = end->prev;
}
}
int main ()
{
struct Node *head = NULL;
insert (&head, 500);
insert (&head, 100);
display (head);
insertMiddle (&head, 200);
display (head);
insertMiddle (&head, 400);
display (head);
insertMiddle (&head, 300);
display (head);
return 0;
}
Output:

List in Forward direction: 100 500

List in backward direction: 500 100

List in Forward direction: 100 200 500

List in backward direction: 500 200 100

List in Forward direction: 100 200 400 500

List in backward direction: 500 400 200 100

List in Forward direction: 100 200 300 400 500

List in backward direction: 500 400 300 200 100


Insertion at the End:
In this insertion operation, the new input node is added at
the end of the doubly linked list; if the list is not empty. The head will be pointed
to the new node, if the list is empty.

Algorithm for inserting an element at the end of the list :-


Step 1 : NOW, IF POINTER = NULL
Step 2 : ASSIGN NEW NODE = POINTER
Step 3 : ASSIGN POINTER = POINTER -> NEXT
Step 4 : ASSIGN NEW NODE -> DATA = VALUE
Step 5 : ASSIGN NEW NODE -> PREV = NULL
Step 6 : ASSIGN EXTRA = START
Step 7 : (REPEAT STEP 8)WHILE EXTRA = EXTRA !->NULL
Step 8 : ASSIGN EXTRA = EXTRA ->NEXT
Step 9 : ASSIGN EXTRA ->NEXT = NEW NODE
Step 10 : ASSIGN NEW NODE -> PREV = EXTRA AND RETURN
Example:

#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
struct Node *prev;
};
void insertLast (struct Node **head, int data)
{
struct Node *newNode = (struct Node *) malloc (sizeof (struct Node));
newNode->data = data;
newNode->next = NULL;
if (*head ==NULL) //need this if there is no node present in linked list at all
{
*head = newNode;
newNode->prev = NULL;
return;
}
struct Node *temp = *head;
while (temp->next != NULL)
temp = temp->next;
temp->next = newNode;
newNode->prev = temp;
}
void insertStart (struct Node **head, int data)
{
struct Node *newNode = (struct Node *) malloc (sizeof (struct Node));
newNode->data = data;
newNode->next = *head;
newNode->prev = NULL;
if (*head != NULL) //If the linked list already had atleast 1 node
(*head)->prev = newNode;
// *head->prev = newNode; would not work it has (*head) must be used
//changing the new head to this freshly entered node
*head = newNode;
}
void display (struct Node *node) // function to print the doubly linked list
{
struct Node *end;
printf ("List in Forward direction: ");
while (node != NULL)
{
printf (" %d ", node->data);
end = node;
node = node->next;
}
printf (" \n List in backward direction: ");
while (end != NULL)
{
printf (" %d ", end->data);
end = end->prev;
}
}
int main ()
{
struct Node *head = NULL;
/*Need & i.e. address as we
need to change head address only needs to traverse
and access items temporarily
*/
insertStart (&head, 12);
insertStart (&head, 16);
insertStart (&head, 20);
insertLast (&head, 10);
insertLast (&head, 14);
insertLast (&head, 18);
insertLast (&head, 11);
/*No need for & i.e. address as we do not
need to change head address
*/
display (head);
return 0;
}

Output:

List in Forward direction:

20 16 12 10 14 18 11

List in backward direction:

11 18 14 10 12 16 20
Deletion at the First/ Beginning:
This deletion operation deletes the existing first nodes in the doubly
linked list. The head is shifted to the next node and the link is removed.

Deletion at Begin:

After the deletion of the node.

Algorithm:

1. START

2. Check the status of the doubly linked list

3. If the list is empty, deletion is not possible

4. If the list is not empty, the head pointer is shifted to the next node.

5. END
Example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node
{
int data;
int key;
struct node *next;
struct node *prev;
};
struct node *head = NULL; //this link always point to first Link
struct node *last = NULL; //this link always point to last Link
struct node *current = NULL;
bool isEmpty() //is list empty
{
return head == NULL;
}
void printList() //display the doubly linked list
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("(%d,%d) ",ptr->key, ptr->data);
ptr = ptr->next;
}
}
void insertFirst(int key, int data) //insert link at the first location
{
struct node *link = (struct node*) malloc(sizeof(struct node)); //create a link
link->key = key;
link->data = data;
if(isEmpty())
{
last = link; //make it the last link
}
else
{
head->prev = link; //update first prev link
}
link->next = head; //point it to old first link
head = link; //point first to new first link
}
struct node* deleteFirst() //delete first item
{
struct node *tempLink = head; //save reference to first link
if(head->next == NULL) //if only one link
{
last = NULL;
}
else
{
head->next->prev = NULL;
}
head = head->next;
return tempLink; //return the deleted link
}
void main()
{
insertFirst(0, 10);
insertFirst(1, 20);
insertFirst(2, 30);
insertFirst(3, 50);
insertFirst(4, 40);
insertFirst(5, 56);
printf(" \n Doubly Linked List: ");
printList();
printf("\n List after deleting first or Begins: ");
deleteFirst();
printList();
}

Output:

Doubly Linked List: (0,10) (1,20) (2,30) (3,40) (4,50) (5,60)

List after deleting first or Begins: (1,20) (2,30) (3,40) (4,50) (5,60)
Deeletion at Middle Position:

create a doubly linked list and delete a node from the middle of the list.
If the list is empty, display the message "List is empty".
If the list is not empty, we will calculate the size of the list and then
divide it by 2 to get the mid-point of the list.
Current will point to head node.
We will iterate through the list till mid?point is reached.
Now current will point to the middle node.
We delete middle node such that current's previous node will point to the
current's next node.

After the deletion of the node.


Algorithm:

1. Define a Node class which represents a node in the list. It will have three
properties: data, previous which will point to the previous node and next
which will point to the next node.
2. Define another class for creating the doubly linked list, and it has two
nodes: head and tail. Initially, head and tail will point to null.
3. deleteFromMid() will delete a node from the middle of the list:
1. It first checks whether the head is null (empty list) then, it will return
from the function as there is no node present in the list.
2. If the list is not empty, it will check whether the list has only one
node.
3. If the list has more than one node then, it will calculate the size of
the list. Divide the size by 2 and store it in variable mid.
4. Iterate through the list till current points to mid node of the list.
5. Connect current's previous node to current?s next node.
6. Delete the current node by setting it to null.
4. display() will show all the nodes present in the list.
1. Define a new node 'current' that will point to the head.
2. Print current.data till current points to null.
3. Current will point to the next node in the list in each iteration.
Example:

#include <stdio.h>
struct node //Represent a node of the doubly linked list
{
int data;
struct node *previous;
struct node *next;
};
int size = 0;
//Represent the head and tail of the doubly linked list
struct node *head, *tail = NULL;
void addNode(int data) //addNode() will add a node to the list
{
//Create a new node
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
if(head == NULL) //If list is empty
{
head = tail = newNode; //Both head and tail will point to newNode
head->previous = NULL; //head's previous will point to NULL
tail->next = NULL; //tail's next will point to NULL, as it is the last node of the list
}
else
{
//newNode will be added after tail such that tail's next will point to newNode
tail->next = newNode;
newNode->previous = tail; //newNode's previous will point to tail
tail = newNode; //newNode will become new tail
tail->next = NULL; //As it is last node, tail's next will point to NULL
}
size++; //Size will count the number of nodes present in the list
}
//deleteFromMid() will delete a node from middle of the list
void deleteFromMid()
{
if(head == NULL) //Checks whether list is empty
{
return;
}
else
{
struct node *current = head; //current will point to head
int mid = (size % 2 == 0) ? (size/2) : ((size+1)/2); //Store the mid position o
f the list
for(int i = 1; i < mid; i++) //Iterate through list till current points to mid position
{
current = current->next;
}
if(current == head) //If middle node is head of the list
{
head = current->next;
}
else if(current == tail) //If middle node is tail of the list
{
tail = tail->previous;
}
else
{
current->previous->next = current->next;
current->next->previous = current->previous;
}
current = NULL; //Delete the middle node
}
size--;
}
void display() //display() will print out the nodes of the list
{
struct node *current = head; //Node current will point to head
if(head == NULL)
{
printf(" List is empty\n ");
return;
}
while(current != NULL)
{
printf("%d ",current->data); //Prints each node by incrementing pointer.
current = current->next;
}
printf(" \n" );
}
int main()
{
addNode(10); //Add nodes to the list
addNode(20);
addNode(30);
addNode(40);
addNode(50);
printf(" Original List: \n"); //Printing original list
display();
while(head != NULL)
{
deleteFromMid();
printf("Updated List: \n"); //Printing updated list
display();
}
return 0;
}
Output:
Original List: 10 20 30 40 50
Updated List: 10 20 40 50
Updated List: 10 40 50
Updated List: 10 50
Updated List: 50
Updated List: List is empty
Deletion at the End:

In this insertion operation, the new input node is added at the end of the doubly
linked list; if the list is not empty. The head will be pointed to the new node, if
the list is empty.

Deletion at End:

After the deletion of the node.

Algorithm:

1. START

2. If the list is empty, add the node to the list and point the head to it.

3. If the list is not empty, find the last node of the list.

4. Create a link between the last node in the list and the new node.

5. The new node will point to NULL as it is the new last node.

6. END
Example:

#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
struct Node *prev;
};
void insert (struct Node **head, int data)
{
struct Node *freshNode = (struct Node *) malloc (sizeof (struct Node));
freshNode->data = data;
freshNode->next = *head;
freshNode->prev = NULL;
if (*head != NULL) // If the linked list already had atleast 1 node
(*head)->prev = freshNode;
*head = freshNode; // freshNode will become head
}
void deleteEnd (struct Node **head)
{
struct Node *tempNode = *head;
if (*head == NULL) // if DLL is empty
{
printf ("Linked List Empty, nothing to delete\n\n");
return;
}
if (tempNode->next == NULL) // if Linked List has only 1 node
{
printf ("%d deleted\n\n", tempNode->data);
*head = NULL;
return;
}
while (tempNode->next != NULL) // else traverse to the last node
tempNode = tempNode->next;
struct Node *secondLast = tempNode->prev;
secondLast->next = NULL; // Curr assign 2nd last node's next to Null
printf ("deleted element\t %d \n\n", tempNode->data);
free (tempNode);
}
void display (struct Node *node) //function to print the doubly linked list
{
struct Node *end = NULL;
while (node != NULL)
{
printf (" %d ", node->data);
end = node;
node = node->next;
}
printf (" \n \n");
}
int main ()
{
struct Node *head = NULL;
insert (&head, 60);
insert (&head, 50);
insert (&head, 40);
insert (&head, 30);
insert (&head, 20);
insert (&head, 10);
printf("Linked List Before Deletion:\n");
display (head);
deleteEnd (&head);
printf("Linked List After Deletion:\n");
display (head);
return 0;
}

Output:

Linked List Before Deletion:

10 20 30 40 50 60

Deleted element: 60

Linked List After Deletion:

10 20 30 40 50
Searching and Sorting
Searching:
Searching refers to a technique that helps us search a data element out of the
given string or array. On the other hand, Sorting refers to the technique used for
rearranging the data elements present in a string or an array in any specified
order, descending or ascending.

1. Sequential Search/ Linear Search

2. Binary Search

Interpolation Search:

Sorting:

Sorting is the process of arranging the elements of an array so that they


can be placed either in ascending or descending order. Or The arrangement of
data in a preferred order is called sorting in the data structure. By sorting data, it
is easier to search through it quickly and easily. Sorting techniques are classified
into…

1. Selection Sort
2. Insertion Sort
3. Bubble Sort
4. Quick Sort
5. Merge Sort
6. Radix Sort
7. Bucket Sort
Difference between Searching and Sorting Algorithm:

Searching Sorting

It is used to find a specific element It is a way to organize data in


in the dataset. increasing or decreasing order.

It does not update the original It updates the original dataset.


dataset.

It can be done by linear search, It can be done by bubble sort, selection


binary search and ternary search. sort, quick sort and merge sort.

It can be done with a single pass It requires multiple passes through the
through the data. data.

The worst-case time complexity of The worst-case time complexity of the


the best searching algorithm is best sorting algorithm is O(nlogn).
O(logn).

The best case time complexity of The best-case time complexity of the
the best searching algorithm is best sorting algorithm is O(n).
O(1).

Search engines like Google use E-commerce websites use sorting


searching algorithms to find algorithms to sort products based on
relevant web pages. price.

A search algorithm can be used for A sorting algorithm can be used for
criteria’s like searching for criteria’s like sorting based on date,
multiple occurrences of a specific sorting based on alphabetical order and
element and finding the closest sorting based on numeric value.
match for an element.
Linear Searching:
Linear search is also called as sequential search algorithm.
It is the simplest searching algorithm.
In Linear search, we simply traverse the list completely and match each
element of the list with the item whose location is to be found.
If the match is found, then the location of the item is returned;
otherwise, the algorithm returns NULL.

Example:
Find the element 33

implementation of Linear Search:

Algorithm:

First, we have to traverse the array elements using a for loop.


In each iteration of for loop compare the search element with the current
array element,
If the element matches, then return the index of the corresponding array
element.
If the element does not match, then move to the next element.
If there is no match or the search element is not present in the given array,
return -1.
Working of linear search:

It will be easy to understand the working of linear search with an example.

Let the element to be searched is K = 41

Now, start from the first element and compare K with each element of the array.

The value of K, i.e., 41, is not matched with the first element of the array. So,
move to the next element. And follow the same process until the respective
element is found.
Binary Search:
Binary search works on sorted arrays.
Binary search begins by comparing an element in the middle of the array
with the target value.
If the target value matches the element, its position in the array is
returned.
If the target value is less than the element, the search continues in the
lower half of the array.

Working of Binary search:

To understand the working of the Binary search algorithm, let's take a sorted
array. It will be easy to understand the working of Binary search with an
example.

There are two methods to implement the binary search algorithm -

Iterative method
Recursive method

Iterative method:

Iterative call is looping over the same block of code multiple times

The recursive method of binary search follows the divide and conquer approach.

mid = (beg + end)/2

beg = 0

end = 8

mid = (0 + 8)/2 = 4. So, 4 is the mid of the array.


Binary_Search: (a, lower_bound/ Begin, upper_bound/
End, val) // 'a' is the given array, 'lower_bound' is the index of the first array
element, 'upper_bound' is the index of the last array element, 'val' is the valu
e to search:

Step 1:
set begin = lower_bound, end = upper_bound, pos = - 1
Step 2:
repeat steps 3 and 4 while beg <=end
Step 3:
set mid = (beg + end)/2
Step 4:
if a[mid] = val
set pos = mid
print pos
go to step 6
else if a[mid] > val
set end = mid - 1
else
set beg = mid + 1
[end of if]
[end of loop]
Step 5:
if pos = -1
print "value is not present in the array"
[end of if]
Step 6: exit
Example:1
#include <stdio.h>
int binarySearch(int a[], int beg, int end, int val)
{
int mid;
if(end >= beg)
{
mid = (beg + end)/2;
if(a[mid] == val) /* if the item to be searched is present at middle */
{
return mid;
}
/* if the item to be searched is smaller than middle, then it can only be in left
subarray */
else if(a[mid] < val)
{
return binarySearch(a, mid+1, end, val);
}
/* if the item to be searched is greater than middle, then it can only be in
right subarray */
else
{
return binarySearch(a, beg, mid-1, val);
}
}
return -1;
}
int main()
{
int a[] = {11, 14, 25, 30, 40, 41, 52, 57, 70}; // given array
int val = 40; // value to be searched
int n = sizeof(a) / sizeof(a[0]); // size of array
int res = binarySearch(a, 0, n-1, val); // Store result
printf("The elements of the array are: ");
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf(" \n Element to be searched is: %d", val);
if (res == -1)
printf(" \n Element is not present in the array");
else
printf(" \n Element is present at %d position of array", res);
return 0;
}
Output:1
The elements of the array are: 11 14 25 30 40 41 52 57 70
Element to be searched is: 40
Element is present at 5 position of array

Output:2
The elements of the array are: 11 14 25 30 40 41 52 57 70
Element to be searched is: 14
Element is present at 1 position of array
Note:
Output2 Key=14
Example:2
#include <stdio.h>
int iterativeBinarySearch(int array[], int start_index, int end_index, int
element)
{
while (start_index <= end_index)
{
int middle = start_index + (end_index- start_index )/2;
if (array[middle] == element)
return middle;
if (array[middle] < element)
start_index = middle + 1;
else
end_index = middle - 1;
}
return -1;
}
int main(void)
{
int array[] = {1, 4, 7, 9, 16, 56, 70};
int n = 7;
int element = 16;
int found_index = iterativeBinarySearch(array, 0, n-1, element);
if(found_index == -1 )
{
printf("Element not found in the array ");
}
else
{
printf("Element found at index : %d", found_index);
}
return 0;
}
Output:
Element found at index: 4

Output:2
Element found at index: 0
Note:
Output 2 key=1
Recursive: Recursive call is calling the same function again and again.
#include <stdio.h>
int binarySearch(int array[], int x, int low, int high)
{
if (high >= low)
{
int mid = low + (high - low) / 2;
if (array[mid] == x) // If found at mid, then return it
return mid;
if (array[mid] > x) // Search the left half
return binarySearch(array, x, low, mid - 1);
return binarySearch(array, x, mid + 1, high); // Search the right half
}
return -1;
}
int main(void)
{
int array[] = {30, 44,50, 66, 77, 88, 99,100};
int n = sizeof(array) / sizeof(array[0]);
int x = 50;
int result = binarySearch(array, x, 0, n - 1);
if (result == -1)
printf("Not found");
else
printf("Element is found @ index: %d", result);
}
Output:

Element is found @ index: 2

Output:2

Element is found @ index: 0

Note:

Output 2 Key= 30
Example:2

#include <stdio.h>

int recursiveBinarySearch(int array[], int start_index, int end_index, int


element)

if (end_index >= start_index)

int middle = start_index + (end_index - start_index )/2;

if (array[middle] == element)

return middle;

if (array[middle] > element)

return recursiveBinarySearch(array, start_index, middle-1, element);

return recursiveBinarySearch(array, middle+1, end_index, element);

return -1;

int main(void)

int array[] = {1, 4, 7, 9, 16, 56, 70};

int n = 7;

int element = 9;

int found_index = recursiveBinarySearch(array, 0, n-1, element);


if(found_index == -1 )

printf("Element not found in the array ");

else

printf("Element found at index : %d",found_index);

return 0;

Output:1

Element not found in the array

Output:2

Output 2 Key= 56
Sorting:

Sorting is the process of arranging the elements of an array so that they can be
placed either in ascending or descending order. Or The arrangement of data in a
preferred order is called sorting in the data structure. By sorting data, it is easier
to search through it quickly and easily. Sorting techniques are classified into…

1. Selection Sort
2. Insertion Sort
3. Bubble Sort
4. Quick Sort
5. Merge Sort
6. Radix Sort
7. Bucket Sort
Selection Sort:

Selection sort is another algorithm that is used for sorting.


This sorting algorithm, iterates through the array and finds the smallest
number in the array and swaps it with the first element if it is smaller than
the first element.
Next, it goes on to the second element and so on until all elements are
sorted.
This sorting algorithm used for limited elements

Implementation:
Algorithm:

Step 1: Set MIN to location 0


Step 2: Search the minimum element in the list
Step 3: Swap with value at location MIN
Step 4: Increment MIN to point to next element
Step 5: Repeat until list is sorted

Step 1: Repeat Steps 2 and 3 for i = 0 to n-1


Step 2: CALL SMALLEST (arr, i, n, pos)
Step 3: SWAP arr[i] with arr[pos]
[END OF LOOP]
Step 4: EXIT

SMALLEST (arr, i, n, pos)


Step 1: [INITIALIZE] SET SMALL = arr[i]
Step 2: [INITIALIZE] SET pos = i
Step 3: Repeat for j = i+1 to n
if (SMALL > arr[j])
SET SMALL = arr[j]
SET pos = j
[END OF if]
[END OF LOOP]
Step 4: RETURN pos
Example:1
#include <stdio.h>
void main()
{
int i, j, a, n, number[30];
printf("Enter the value of N \n");
scanf("%d", &n);
printf("Enter the numbers \n");
for (i = 0; i < n; ++i)
scanf("%d", &number[i]);
for (i = 0; i < n; ++i)
{
for (j = i + 1; j < n; ++j)
{
if (number[i] > number[j])
{
a = number[i];
number[i] = number[j];
number[j] = a;
}
}
}
printf("The numbers arranged in ascending order are given below \n");
for (i = 0; i < n; ++i)
printf("%d\n", number[i]);
}
Output:
Enter the value of N
5
Enter the numbers
10
20
11
99
2
The numbers arranged in ascending order are given below
2
10
11
20
99
Example:2
#include <stdio.h>
int main()
{
int arr[10]={ 14,33,27,10,35,19,42,44};
int n=8;
int i, j, position, swap;
for (i = 0; i < (n - 1); i++)
{
position = i;
for (j = i + 1; j < n; j++)
{
if (arr[position] > arr[j])
position = j;
}
if (position! = i)
{
swap = arr[i];
arr[i] = arr[position];
arr[position] = swap;
}
}
for (i = 0; i < n; i++)
printf("%d\t", arr[i]);
return 0;
}
Output: 10 14 19 27 33 35 42 44
Example:3
#include <stdio.h>
void swap(int *a, int *b) // function to swap the the position of two elements
{
int temp = *a;
*a = *b;
*b = temp;
}
void selectionSort(int array[], int size)
{
for (int step = 0; step < size - 1; step++)
{
int min_idx = step;
for (int i = step + 1; i < size; i++)
{
// To sort in descending order, change > to < in this line.
// Select the minimum element in each loop.
if (array[i] < array[min_idx])
min_idx = i;
}
swap(&array[min_idx], &array[step]); // put min at the correct position
}
}
void printArray(int array[], int size) // function to print an array
{
for (int i = 0; i < size; ++i)
{
printf("%d ", array[i]);
}
printf("\n");
}
int main() // driver code
{
int data[] = {20, 12, 10, 15, 2};
int size = sizeof(data) / sizeof(data[0]);
selectionSort(data, size);
printf("Sorted array in Ascending Order:\n");
printArray(data, size);
}
Output:
Sorted array in Ascending Order:
2 10 12 15 20
Bubble sort:
Bubble sort is a simple sorting algorithm.
This sorting algorithm is comparison-based algorithm in which each pair
of adjacent elements is compared and the elements are swapped if they
are not in order.
This algorithm is not suitable for large data sets as its average and worst-
case complexity are of Ο(n2) where n is the number of items.
Implementation:
The bubble sort, also known as the ripple sort, is one of the least efficient
sorting algorithms.
However, it is probably the simplest to understand. At each step, if two
adjacent elements of a list are not in order, they will be swapped.
Thus, larger elements will “bubble” to the end, (or smaller elements will
be “bubbled” to the front, depending on implementation) and hence the
name.
The principle of a bubble sort is illustrated below:
Compare the first two values and swap if necessary.
Then compare the next pair of values and swap if necessary.
This process is repeated n-1 times, where n is the number of values being
sorted.
The example below sorts 4 numbers into ascending numerical order.
this requires 3 (n-1) passes to achieve since there are 4 items of data.
The bigger numbers can be seen to bubble (or ripple) to the top.
Sorting will start from the initial two elements.
Let compare them to check which is greater.

Algorithm:

begin BubbleSort(list)
for all elements of list
if list[i] > list[i+1]
swap(list[i], list[i+1])
end if
end for
return list
end BubbleSort
Example:1
#include <stdio.h>
int main()
{
int array [10], n, i, j, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d elements\n", n);
for (i = 0; i < n; i++)
scanf("%d", &array[i]);
for (i = 0 ; i < n - 1; i++)
{
for (j = 0; j < n - i - 1; j++)
{
if (array[j] > array[j+1]) /* For decreasing order use '<' instead of '>' */
{
swap= array[j];
array[j] = array[j+1];
array[j+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n");
for (i = 0; i < n; i++)
printf("%d \n", array[i]);
return 0;
}
Output:
Enter number of elements
5
Enter 5 elements
14 33 27 35 10
Sorted list in ascending order:
10 14 27 33 35
Example:2
#include <stdio.h>
#define max 20
int a[11] = { 10, 14, 19, 26, 27, 31, 33, 35, 42, 44, 0 };
int b[10];
void merging(int low, int mid, int high)
{
int l1, l2, i;
for(l1 = low, l2 = mid + 1, i = low; l1 <= mid && l2 <= high; i++)
{
if(a[l1] <= a[l2])
b[i] = a[l1++];
else
b[i] = a[l2++];
}
while(l1 <= mid)
b[i++] = a[l1++];
while(l2 <= high)
b[i++] = a[l2++];
for(i = low; i <= high; i++)
a[i] = b[i];
}
void sort(int low, int high)
{
int mid;
if(low < high)
{
mid = (low + high) / 2;
sort(low, mid);
sort(mid+1, high);
merging(low, mid, high);
}
else
{
return;
}
}
int main()
{
int i;
printf("List before sorting:\n");
for(i = 0; i <= max; i++)
printf("%d ", a[i]);
sort(0, max);
printf(" \n List after sorting:\n");
for(i = 0; i <= max; i++)
printf("%d ", a[i]);
}
Output:
List before sorting:
10 14 19 26 27 31 33 35 42 44 0
List after sorting:

0 10 14 19 26 27 31 33 35 42 44
Insertion sort:
Insertion sort works similar to the sorting of playing cards in hands.
It is assumed that the first card is already sorted in the card game, and
then we select an unsorted card.
If the selected unsorted card is greater than the first card, it will be placed
at the right side;
otherwise, it will be placed at the left side.
Similarly, all unsorted cards are taken and put in their exact place.
Algorithm for Insertion Sort:

Step 1: If the element is the first one, it is already sorted.

Step 2: Move to next element

Step 3: Compare the current element with all elements in the sorted array

Step 4: If the element in the sorted array is smaller than the current element,

iterate to the next element. Otherwise, shift all the greater element in the

array by one position towards the right

Step 5: Insert the value at the correct position

Step 6: Repeat until the complete list is sorted


Example:1 Insertion

#include <stdio.h>
int main(void)
{
int n, i, j, temp;
int arr[10];
printf(" Enter number of elements \n ");
scanf("%d", &n);
printf(" Enter %d Elements \n", n);
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
for (i = 1; i < n; i++)
{
j = i;
while (j > 0 && arr[j - 1] > arr[j])
{
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
j--;
}
}
printf("Sorted list in ascending order:\n");
for (i = 0; i < n; i++)
{
printf("%d\t", arr[i]);
}
return 0;
}
Output:
Enter number of elements
8
Enter 8 Elements
4 3 2 10 12 1 5 6
Sorted list in ascending order:
1 2 3 4 5 6 10 12
Merge sort:
Merge sort is one of the most efficient sorting algorithms. It is based
on the divide-and-conquer strategy. Merge sort continuously cuts down a list
into multiple sub lists until each has only one item, then merges those sub lists
into a sorted list.
In computer science, divide and conquer is an algorithm design paradigm. A
divide-and-conquer algorithm recursively breaks down a problem into two or
more sub-problems of the same or related type, until these become simple
enough to be solved directly.

1. Divide the original problem into a set of subproblems.


2. Conquer: Solve every subproblem individually, recursively.
3. Combine: Put together the solutions of the subproblems to get the solution
to the whole problem.
Example: 38 27 43 3 9 82 10

Algorithm for Merge Sort

Step 1: Find the middle index of the array.


Middle = 1 + (last – first)/2
Step 2: Divide the array from the middle.
Step 3: Call merge sort for the first half of the array
MergeSort(array, first, middle)
Step 4: Call merge sort for the second half of the array.
MergeSort(array, middle+1, last)
Step 5: Merge the two sorted halves into a single sorted array.
Example:
#include <stdio.h>
// function to sort the subsection a[i .. j] of the array a[]
void merge_sort(int i, int j, int a[], int aux[])
{
if (j <= i)
{
return; // the subsection is empty or a single element
}
int mid = (i + j) / 2;
// left sub-array is a[i .. mid]
// right sub-array is a[mid + 1 .. j]
merge_sort(i, mid, a, aux); // sort the left sub-array recursively
merge_sort(mid + 1, j, a, aux); // sort the right sub-array recursively
int pointer_left = i; // pointer_left points to the beginning of the left sub-array
int pointer_right = mid + 1; // pointer_right points to the beginning of the right
sub-array
int k; // k is the loop counter
for (k = i; k <= j; k++) // we loop from i to j to fill each element of the final
merged array
{
if (pointer_left == mid + 1) // left pointer has reached the limit
{
aux[k] = a[pointer_right];
pointer_right++;
}
else if (pointer_right == j + 1) // right pointer has reached the limit
{
aux[k] = a[pointer_left];
pointer_left++;
}
else if (a[pointer_left] < a[pointer_right]) // pointer left points to smaller
element
{
aux[k] = a[pointer_left];
pointer_left++;
}
else
{
aux[k] = a[pointer_right]; // pointer right points to smaller element
pointer_right++;
}
}
for (k = i; k <= j; k++)
{
a[k] = aux[k]; // copy the elements from aux[] to a[]
}
}
int main()
{
int a[100], aux[100], n, i, d, swap;
printf(" Enter number of elements in the array:\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
merge_sort(0, n - 1, a, aux);
printf("Printing the sorted array:\n");
for (i = 0; i < n; i++)
printf("%d\t", a[i]);
return 0;
}
Output:
Enter number of elements in the array:
7
Enter 7 integers
38 27 43 3 9 82 10
Printing the sorted array:
3 9 10 27 38 43 82
Quick Sort:
Quicksort was developed by British computer scientist Tony
Hoare in 1959 and published in 1961. Quicksort is most efficient sorting
algorithm It is still a commonly used algorithm for sorting. In quick sort, a large
array is divided into two arrays in which one holds values that are smaller than
the specified value (Pivot), and another array holds the values that are greater
than the pivot. After that, left and right sub-arrays are also partitioned using the
same approach.
Or
The average time complexity of quick sort is O(N log(N)). Quick
Sort is a sorting algorithm that works using the Divide and Conquer approach. It
chooses a pivot and places it in its correct position in the sorted array and
partitions the smaller elements to its left and the greater ones to its right.
In computer science, divide and conquer is an algorithm design paradigm. A
divide-and-conquer algorithm recursively breaks down a problem into two or
more sub-problems of the same or related type, until these become simple
enough to be solved directly.

1. Divide the original problem into a set of subproblems.


2. Conquer: Solve every subproblem individually, recursively.
3. Combine: Put together the solutions of the subproblems to get the solution
to the whole problem.

How to Choose the pivot:

Picking a good pivot is necessary for the fast implementation of quicksort.


However, it is typical to determine a good pivot. Some of the ways of choosing a
pivot are as follows:

Pivot can be random, i.e., select the random pivot from the given array.
Pivot can either be the rightmost element of the leftmost element of the
given array.
Select median as the pivot element.
Quick Sort Pivot Algorithm:
Based on our understanding of partitioning in
quick sort, we will now try to write an algorithm for it, which is as follows.

Step 1: Choose the pivot following any of the four methods (the last element

is commonly used as the pivot).

Step 2: Assign the counter i to the leftmost element’s index and the counter

j to the rightmost element’s index, excluding the counter.

Step 3: If i is less than j, proceed.

Step 4: If the element in position i is less than the pivot, increment i.

Step 5: If the element in position j is greater than the pivot, decrement j.

Step 6: If the element in i is greater than the pivot and the element in

position j is less than the pivot, swap the elements in i and j.

Step 7: If i is greater than j, swap the element in position i and the pivot.

Step 8: Continue the process for the left and the right partitions formed.

QUICKSORT (array A, start, end)


{
if (start < end)
{
p = partition (A, start, end)
QUICKSORT (A, start, p - 1)
QUICKSORT (A, p + 1, end)
}
}
With this, we have completed the partition.

Now, for the quicksort part,

Step 1: Declare a function with three parameters, an array (say arr) and two

integer type variables (say i and j).

Step 2: If arr[i] < arr[j], partition the array between arr[i] and arr[j].

Step 3: Recursively call the function with three parameters, an array (arr) and

two integers (i and (partition position - 1)).

Step 4: Recursively call the function with three parameters, an array (arr) and

two integers ((partition position + 1), j).

Implementation: 24, 9, 29, 14, 19, 27

In the given array, we consider the leftmost element as pivot. So, in this case,
a[left] = 24, a[right] = 27 and a[pivot] = 24.

Since, pivot is at left, so algorithm starts from right and move towards left.

Now, a[pivot] < a[right], so algorithm moves forward one position towards left

(24<27)
Now, a[left] = 24, a[right] = 19, and a[pivot] = 24.

(24>19)

Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right], and
pivot moves to right,

Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so
algorithm starts from left and moves to right. (24>19)

As a[pivot] > a[left], so algorithm moves one position to right as


Now, a[left] = 9, a[right] = 24, and a[pivot] = 24. As a[pivot] > a[left], so
algorithm moves one position to right as, (24>9)

Now, a[left] = 29, a[right] = 24, and a[pivot] = 24. As a[pivot] < a[left], so,
swap a[pivot] and a[left], now pivot is at left, (24<29)

Since, pivot is at left, so algorithm starts from right, and move to left. Now,
a[left] = 24, a[right] = 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm
moves one position to left, (24>14)
Now, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right], so,
swap a[pivot] and a[right], now pivot is at right

Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the
algorithm starts from left and move to right.

Now, a[pivot] = 24, a[left] = 24, and a[right] = 24. So, pivot, left and right are
pointing the same element. It represents the termination of procedure.

Element 24, which is the pivot element is placed at its exact position.

Elements that are right side of element 24 are greater than it, and the elements
that are left side of element 24 are smaller than it.
Now, in a similar manner, quick sort algorithm is separately applied to the left
and right sub-arrays. After sorting gets done,
Example:1
#include<stdio.h>
void swap(int *x, int *y) // A utility function to swap two elements
{
int temp = *x;
*x = *y;
*y = temp;
}
/* Partition function to do Partition
elements on the left side of pivot elements would be smaller than pivot
elements on the right side of pivot would be greater than the pivot
*/
int partition (int array[], int low, int high)
{
// pivot element selected as right most element in array each time
int pivot = array[high];
int swapIndex = (low - 1); //swapping index
for (int j = low; j <= high- 1; j++)
{
if (array[j] < pivot) // Check if current element is smaller than pivot element
{
swapIndex ++; // increment swapping index
swap(&array[swapIndex], &array[j]);
}
}
swap(&array[swapIndex + 1], &array[high]);
return (swapIndex + 1);
}
void quickSort(int array[], int low, int high) //Recursive function to apply
quickSort
{
if (low < high)
{
//indexPI is partitioning index, partition() function will return index of partition
int indexPI = partition(array, low, high);
quickSort(array, low, indexPI - 1); // left partition
quickSort(array, indexPI + 1, high); // right partition
}
}
void display(int array[], int size) /* Function to display the array */
{
int i;
for (i=0; i < size; i++)
printf("%d ", array[i]);
}
int main() //Main function to run the program
{
int array[] = {70, 90, 10, 30, 50, 20, 60};
int size = sizeof(array)/sizeof(array[0]);
quickSort(array, 0, size-1);
printf("Array after Quick Sorting: ");
display(array, size);
return 0;
}
Output:
Array after Quick Sorting:
10 20 30 50 60 70 90
Example:2
#include<stdio.h>
void quicksort(int number[25], int first, int last)
{
int i, j, pivot, temp;
if(first<last)
{
pivot=first;
i=first;
j=last;
while(i<j)
{
while(number[i]<=number[pivot]&&i<last)
i++;
while(number[j]>number[pivot])
j--;
if(i<j)
{
temp=number[i];
number[i]=number[j];
number[j]=temp;
}
}
temp=number[pivot];
number[pivot]=number[j];
number[j]=temp;
quicksort(number, first, j-1);
quicksort(number, j+1, last);
}
}
int main()
{
int i, count, number[25];
printf("Enter some elements (Max. - 25): ");
scanf("%d", &count);
printf("Enter %d elements: ", count);
for(i=0; i<count; i++)
scanf("%d", &number[i]);
quicksort(number, 0, count-1);
printf("The Sorted Order is: ");
for(i=0; i<count; i++)
printf(" %d", number[i]);
return 0;
}

Output:
Enter some elements (Max. - 25):
10
Enter 10 elements: 10 9 99 77 88 22 11 33 18 0

The Sorted Order is: 0 9 10 11 18 22 33 77 88 99


Heap Sorting:
Heap sort processes the elements by creating the min-heap or
max-heap using the elements of the given array. Min-heap or max-heap
represents the ordering of array in which the root element represents the
minimum or maximum element of the array.

What is a heap?

A heap is a complete binary tree, and the binary tree is a tree in


which the node can have the utmost two children. A complete binary tree is a
binary tree in which all the levels except the last level, i.e., leaf node, should be
completely filled, and all the nodes should be left-justified.

What is heap sort?

Heapsort is a popular and efficient sorting algorithm. The


concept of heap sort is to eliminate the elements one by one from the heap part of
the list, and then insert them into the sorted part of the list.

Heapsort is the in-place sorting algorithm.

Detailed Working of Heap Sort


To understand heap sort more clearly, let’s take an unsorted array and try to sort
it using heap sort.
Consider the array: arr[] = {4, 10, 3, 5, 1}.
Transform into max heap: After that, the task is to construct a tree from that
unsorted array and try to convert it into max heap.
 To transform a heap into a max-heap, the parent node should always be
greater than or equal to the child nodes
 Here, in this example, as the parent node 4 is smaller than the child
node 10, thus, swap them to build a max-heap.
 Now, 4 as a parent is smaller than the child 5, thus swap both of these
again and the resulted heap and array should be like this:

Perform heap sort: Remove the maximum element in each step (i.e., move it to
the end position and remove that) and then consider the remaining elements and
transform it into a max heap.
Delete the root element (10) from the max heap. In order to delete this
node, try to swap it with the last node, i.e. (1). After removing the root
element, again heapify it to convert it into max heap.
Resulted heap and array should look like this:
Now when the root is removed once again it is sorted. and the sorted array will
be like arr[] = {1, 3, 4, 5, 10}.
Example: 1

#include <stdio.h>
// Function to swap the position of two elements
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// To heapify a subtree rooted with node i
// which is an index in arr[].
// n is size of heap
void heapify(int arr[], int N, int i)
{
// Find largest among root,
// left child and right child
// Initialize largest as root
int largest = i;
// left = 2*i + 1
int left = 2 * i + 1;
// right = 2*i + 2
int 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;
// Swap and continue heapifying
// if root is not largest
// If largest is not root
if (largest != i)
{
swap(&arr[i], &arr[largest]);
// Recursively heapify the affected
// sub-tree
heapify(arr, N, largest);
}
}
// Main function to do heap sort
void heapSort(int arr[], int N)
{
// Build max heap
for (int i = N / 2 - 1; i >= 0; i--)
heapify(arr, N, i);
// Heap sort
for (int i = N - 1; i >= 0; i--)
{
swap(&arr[0], &arr[i]);
// Heapify root element
// to get highest element at
// root again
heapify(arr, i, 0);
}
}
// A utility function to print array of size n
void printArray(int arr[], int N)
{
for (int i = 0; i < N; i++)
printf("%d ", arr[i]);
printf("\n");
}
// Driver's code
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function call
heapSort(arr, N);
printf("Sorted array is\n");
printArray(arr, N);
}
Output:
Sorted array is
5 6 7 11 12 13
Example:2
#include <stdio.h>
/* function to heapify a subtree. Here 'i' is the
index of root node in array a[], and 'n' is the size of heap. */
void heapify(int a[], int n, int i)
{
int largest = i; // Initialize largest as root
int left = 2 * i + 1; // left child
int right = 2 * i + 2; // right child
// If left child is larger than root
if (left < n && a[left] > a[largest])
largest = left;
// If right child is larger than root
if (right < n && a[right] > a[largest])
largest = right;
// If root is not largest
if (largest != i)
{
// swap a[i] with a[largest]
int temp = a[i];
a[i] = a[largest];
a[largest] = temp;

heapify(a, n, largest);
}
}
/*Function to implement the heap sort*/
void heapSort(int a[], int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify(a, n, i);
// One by one extract an element from heap
for (int i = n - 1; i >= 0; i--)
{
/* Move current root element to end*/
// swap a[0] with a[i]
int temp = a[0];
a[0] = a[i];
a[i] = temp;

heapify(a, i, 0);
}
}
/* function to print the array elements */
void printArr(int arr[], int n)
{
for (int i = 0; i < n; ++i)
{
printf("%d", arr[i]);
printf(" ");
}

}
int main()
{
int a[] = {48, 10, 23, 43, 28, 26, 1};
int n = sizeof(a) / sizeof(a[0]);
printf("Before sorting array elements are - \n");
printArr(a, n);
heapSort(a, n);
printf("\n After sorting array elements are - \n");
printArr(a, n);
return 0;
}
Output:
Before sorting array elements are -
48 10 23 43 28 26 1
After sorting array elements are -
1 10 23 26 28 43 48

You might also like