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

DSA Book

DSA book

Uploaded by

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

DSA Book

DSA book

Uploaded by

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

PrepInsta Handbook for Coding

For Placement Preparation

PrepInsta Technologies Pvt Ltd


Preface:

This book contains all the information regarding DSA which is asked in Placement Tests. Nowadays you will see many books
and online pages providing information on DSA. Mostly those books contain one section i.e either the coding questions or the
theoretical part. There is no such proper book providing all the updated information at one single place.

This book contains various questions and theory knowledge of all the types asked in Placement tests. This book carries all the
theory and practice questions along with examples and shortcut methods.

It is hoped that the subject matter will instill trust in the applicants, and that the book will assist them in finding an ideal teacher.

Disclaimer: This book is made and published under the complete knowledge and expertise of the Author, however if there will be
any error then it will be taken care of in the next Revised edition. Constructive suggestions and feedback are most welcome by
our esteemed readers.

1
First Edition ● The correct price of the book is already
mentioned on this page. Any revised price on the
May 2021 frontend or backend of the book is not
Edition: 1 (2021) acceptable.

Address of the Publisher:


Published on GSM Paper with PrepInsta WaterMark
K-3, Director Vidyamandir Shastri Nagar, Meerut, UP,
Publisher Address: K-3, Director Vidyamandir Shastri 250004
Nagar, Meerut, UP, 250004

Type settings : PrepInsta Technologies Private Limited Publication Team:

Printer Name: Creative Print Arts PrepInsta Technologies Private Limited

All rights Reserved:

● All the rights are reserved to the PrepInsta


Technologies and no part of the publication can
be stored or re-sold without the prior permission
of the publisher.

Price- Rs.999/-

2
Contents

Chapter 1- Linear Search 4

Chapter 2. Binary Search 6

Chapter 3: Classification of sorting Algorithms 9

Chapter 4: Bubble sorts 10

Chapter 5- Insertion Sort 13

Chapter 6- Selection sort 16

Chapter 7- Merge Sort 19

Chapter 8: Quick Sort 23

Chapter 9: Counting Sort 26

Chapter 10: Radix Sort 30

Chapter 11: Heap Sort 34

Chapter 12: Stacks 37

Chapter 13. Linked Lists 80

Chapter 14. Linked List in C 87

3
7. print element not found
8. exit
Chapter 1. Linear search
What is Linear Search ?

Searching, in normal ways, can be coined as” to find the


hidden thing”. In data structure.the searching algorithm is
used to find whether a given number is present and if it is
present then at what location it occurs.

There are two types of searching algorithms present in data


structure through which searching any data becomes easier.

1. Linear search or sequential search


2. Binary search

C Code:-
Implementation:-
#include <stdio.h> //header files
● Step 1- The list given is the list of elements in an int main () //main function
unsorted array. {
● Step 2- The element to be searched is called an int a[10] = {10, 23, 40, 1, 2, 0, 14, 13, 50, 9};
item, as mentioned in the image, so the value int item, i, flag;
item is compared with all the elements of the
array starting from the 0th element. printf("\nEnter Item which is to be find\n");
● Step 4- As soon as any index contains the same scanf("%d",&item);
value, we stop further comparisons and change
flag value from 0 to 1 //looping logic
● Step 4- If the value is not found until the end of for (i = 0; i< 10; i++)
the array then stop and print value not found {
// if else condition
if(a[i] == item)
Algorithm:- {
flag = i+1;
1. i=1 break;
2. if i>n,go to step 7 }
3. if A[i]=x,go to step 6 else
4. i=i+1 flag = 0;
5. Go to step 2 }
6. print element x found at i

4
if(flag != 0) {
{ int l = ar.length;
//printing the element which is to find for(int i = 0; i < l; i++)
printf("\nItem found at location %d\n",flag); {
} if(ar[i] == s)
else return i;
{ }
printf("\nItem not found\n"); return -1;
} }
return 0; public static void main(String args[])
} {
int ar[] = { 2, 3, 4, 10, 40 };
System.out.println("Enter a number you want to search
for - ");
Scanner s= new Scanner(System.in);
C++ Code
int num=s.nextInt();
#include <iostream> int result = search(ar, num)+1;
using namespace std; if(result == -1)
int main() System.out.print("Element not found.");
{ else
int list[100],size,i,search_el;//Initializing variables. System.out.print("Element found at index " + result);
}
cout<<"Enter size of the list: ";//Taking inputs. }
cin>>size;

cout<<"Enter elements of the list: "; Output:-


for(i = 0; i < size; i++) Enter Item which is to be find
cin>>list[i]; 23
Item found at location 2
cout<<"Enter the element to be search: "; Enter Item which is to be find
cin>>search_el; 3
Item not found
//Searching element using linear search. More about Linear Search
for(i = 0; i < size; i++) Pros
{ 1. Very easy to understand and implement
if(search_el == list[i]) 2. Quick to write the code
{
cout<<"Element is found at "<< i+1 <<" place in the Cons
list"; 1. Time complexity is bad
break; 2. Binary Search gives better, efficient and faster results
}
}
if(i == size) Time Complexity For Linear Search
cout<<"Element is not present in the list";
Best
}
O(1)
Java Code
Average
import java.util.*;
public class Main O(n)
{
public static int search(int ar[], int s) Worst

5
O(n)

Space Complexity

O(1)

Average Comparisons

(n+1)/2

Question 1. The average number of key comparisons done


in a successful sequential search in a list of length it is –

1. (n-1)/2
Chapter 2. Binary Search
2. Log n
3. (n+1)/2
4. (n)/2 What is Binary Search ?

(Amazon – Mettl Test) Binary search is a very fast and efficient searching
algorithm. It requires to be list be in a sorted order, ie;
Solution & Explanation either in ascending or descending.In this method, to search
an element you might compare that respective element
Just say if you have to find a given element in a sequential present in the center of the list and if it’s same then the
search. It can be found in the first try, then 1 comparison is search is successfully finished and if not, then the list is
required similarly…total comparisons can be 1+2+…+n = divided into two parts:one from 0th element to the centered
n(n+1)/2 element and other from the centered element to the last
element.
Avg will be n(n+1)/2 divided by n ( total elements) = How Binary Search works?
(n+1)/2 1. The searching algorithm proceed from any of two halves
2. Depends upon whether the element you are searching is
Ans. Option C greater or smaller than the central element
3. If the element is small then, searching is done in first half
Question 2. The worst-case occurred in the linear search 5. If it is big then searching is done in the second half.
algorithm when
It is a fast search algorithm with the complexity of O(log
1. The element in the middle of an array n).
2. Item present in the last
3. Item present in the starting
4. Item has the maximum value

(TCS NQT)

Solution & Explanation

If the element is situated at the end of the array, it takes


maximum time to search for that element.

Ans. Option B

6
Implementation of Binary Search

● Step 1- In the Given array, first you need to find


the middle of the list using formula
mid=(min+max)/2.

Step 2-If the searched element ie; say 15(in context with
the image given below) is in the center then the search is
terminated, as we can see here it is not.

Step 3- With the help of this algorithm we will try to find


the value. First of all you have to define two variables low
Algorithm of Binary Search
and high so low is 3 and high is 22. Now you have to find
Step 1- while low < high
the mid element.so we will find the mid value of the
formula.
do mid <-(low+high)

Step 4- We would know that in which half the searching


Step 2- if V=A[mid]
would be done.
return mid
Step 5- So we would go for the second half as the searching
element i.e; 15 is greater than the mid element i.e 12.
Step 3- if V=A[mid]
Step 6- The process repeats until we find the element.
low<- mid+1

Step 4- else high<- mid-1

Step 5- return Nil

C Code
#include<stdio.h> //header files

int binarySearch(int[], int, int, int);

7
int main() //main function cin>>search_element;
{
int arr[10] = {9, 26, 33, 47, 53, 60, 75, 80, 86, 99}; location = binarySearch(arr, 0, 9, search_element);
int item, location = -1;
if(location != -1)
printf("Enter the item which you want to find "); {
scanf("%d",&item); cout<<"Search element found at"<<location<<"
location"; //Printing the result.
location = binarySearch(arr, 0, 9, item); }
else
if(location != -1) //looping logic {
{ cout<<"Search element not present";
printf("Item found at location %d",location); //printing }
the element return 0;
} }
else
{ int binarySearch(int a[], int left, int right, int
printf("Item not found"); search_element)
} {
return 0; int middle;
} if(right >= left)
{
int binarySearch(int a[], int start, int last, int item) middle = (left + right)/2;
{ if(a[middle] == search_element) //Checking if elemnet is
int mid; present at middle.
if(last >= start) {
{ return middle+1;
mid = (start + last)/2; }
if(a[mid] == item){ else if(a[middle] < search_element) //Checking if
return mid+1; elemnet is present in greater half.
} {
else if(a[mid] < item){ return binarySearch(a,middle+1,right,search_element);
return binarySearch(a,mid+1,last,item); }
} else //Checking if elemnet is present in samller half.
else{ {
return binarySearch(a,start,mid-1,item); return binarySearch(a,left,middle-1,search_element);
} }
}
return -1; }
} return -1;
}
C++ Code Java Code
import java.util.*;
#include <iostream>//Header file. class Main {
using namespace std; int search(int arr[], int x)
{
int binarySearch(int[], int, int, int); int l = 0, r = arr.length - 1;
while (l <= r) {
int main() //Main function. int m = l + (r - l) / 2;
{
int arr[10] = {19, 26, 37, 53, 56, 61, 77, 82, 87, 91}; if (arr[m] == x) //if x is in the middle
int search_element, location=-1; return m;
if (arr[m] < x) //if x is greater, search the right half
cout<<"Enter the element which you want to search: "; l = m + 1;

8
else //if x is smaller, search the left half Exercise
r = m - 1; Question 1.Binary search algorithm can’t be applied to
}
return -1; //not found 1. Pointed Array List
} 2. Sorted Binary Tree
public static void main(String args[]) 3. Unordered Array
{ 4. Sorted Linked List
Main s=new Main();
Scanner sc= new Scanner(System.in); (Cisco, Walmart Labs)
System.out.println("Enter the element to be searched
"); Solution & ExplanationYou cannot use a binary search on
int num=sc.nextInt(); an unsorted list. Your best bet is to probably iterate over the
int arr[]={3,5,6,7,10,14,15,75,88,96,99}; list’s items until you find the element you are looking for,
int result = s.search(arr, num); an O(n) operation, i.e. do linear search
if (result == -1)
System.out.println("No match found in the Array"); Ans. C
else
System.out.println("Match found at index " + Question 2. Which of the following searching algorithms
result); works on the divide and conquer?
}
} 1. Binary Search
2. Linear
Output:- 3. Sequential
Enter the item which you want to find 26 4. Merge Sort
Item found at location 2
Enter the item which you want to find 3 (CoCubes, Atos Syntel)
Item not found
Solution & ExplanationBinary search only checks the
middle element of the array. when it checks the middle
Time Complexity For Binary Search
element and middle element is not equal to the given
element then we divide the list in two subparts.Ans: Both A
Best &D

O(1)

Average

O(log n) Chapter 3. Classification of


Worst Sorting Algorithms
O(log n) Stable Vs Unstable Sorting
Stable sort sorts the identical elements in their same order
Space Complexity as they appear in the input.

O(1)
Examples: Bubble sort, Insertion sort, Merge Sort,

Average Comparisons Counting sort

In unstable sort, order of identical elements is not


Log(N+1)

9
guranteed to stay in the same order as they appeared in the Examples: Bubble Sort, Selection Sort, Insertion Sort, Heap

input. Examples: Quick Sort, Heap Sort, Selection sort Sort

Not-In-Place Sorting is that which uses auxiliary data


● Stability is not an issue when equal elements are
structure to sort the array.
indistinguishable such as with integers.
● Any given sorting algorithm which is not stable Examples: Merge Sort ( It requires additional O(n) space to
can be modified to stable.
● Generally, unstable sorting is faster than stable perform the merge operation), Quick Sort
sorting.
● We need a stable sort to sort the cards by their
numbers and suit.

Internal Vs External Sort


Internal sorting is that which takes place entirely within the

main memory of the computer. It comes into play when the

dataset is small.

External sorting is that which can handle massive amounts

of data at a time. Data resides in the hard disk in case of

external sorting.
Chapter 4. Bubble Sort

Comparison based Sorting and Counting based Sorting Sorting is the process of arranging the data in some logical

In Comparison based sorting, a comparator is required to order. Bubble sort is an algorithm to sort various linear

compare numbers or items. This comparator defines the data structures.

ordering to arrange the elements. The logical order can be ascending and descending in case

of numeric values or dictionary order in case of


Examples: Merge Sort, Quick Sort, Heap Sort
alphanumeric values.

Bubble Sort is very simple and easy to implement sorting


Counting based sorting is the algorithm that performs the
technique.
sorting without comparing the elements rather by making
In bubble sort technique,each pair of elements is compared.
certain assumptions about the data they are going to sort.
Elements are swapped if they are not in order.
Examples: Counting sort, Radix sort The worst case complexity of bubble sort is O(n2).
In-Place and Not-In-Place Sorting

In-Place Sorting means to sort the array by modifying the Implementation of Bubble Sort
element order directly within the array.
Let’s take an example ,we have a list of number stored in
● No auxiliary data structure is used. array
● There can be only a constant amount of extra
space usually less than log(n). So this algorithm
is space efficient.

10
Logic starts with comparison of the first two elements and [END OF INNER LOOP]

if the left element is greater than the right element,they [END OF OUTER LOOP

swap their position. comparison continues till the end of the Step 4: Return

array.
C Code:-
If we talk about the example taken in the below image, the

first will be in between 28 and 6. #include <stdio.h>

Since the left element i.e; 6 is smaller than the right


/* Function to print array */
element i.i; 28, they will get swapped. void display(int arr[], int size)
{
int i;
Similarly, in the next iteration we will compare 28 and 4,
for (i=0; i < size; i++)
and again they will get swapped. printf("%d ", arr[i]);
printf("\n");
}
This process will continue until the loop reaches the end of
// Main function to run the program
the array, this will be regarded as Pass 1, at the end of
int main()
which we have the largest element on the right most end. {
int array[] = {5, 3, 1, 9, 8, 2, 4,7};
int size = sizeof(array)/sizeof(array[0]);
Passes like this will continue until we have all the elements

in their correct order, you can refer to the image below, for printf("Before bubble sort: \n");
display(array, size);
better understanding.
int i, j, temp;
for (i = 0; i < size-1; i++){

// Since, after each iteration righmost i elements are


sorted
for (j = 0; j < size-i-1; j++)
if (array[j] > array[j+1])
{
temp = array[j]; // swap the element
array[j] = array[j+1];
array[j+1] = temp;
}
}
printf("After bubble sort: \n");
display(array, size);
return 0;
Algorithm of Bubble Sort }

Step 1: Repeat for round=1,2,3…..N-1


C++ Code
#include <iostream>
Step 2: Repeat For i=0,1,2…N-1 round using namespace std;
Step 3: IF A[i] > A[i+1] void swap(int *var1, int *var2)
{
SWAP A[i] and A[i+1] int temp = *var1;
*var1 = *var2;

11
*var2 = temp;
} /* Prints the array */
//Here we will implement bubbleSort. void printArray(int a[])
void bubbleSort(int arr[], int n) {
{ int len = a.length;
int i, j; for (int i=0; i<len; i++)
for (i = 0; i < n-1; i++) System.out.print(a[i] + " "); //printing the sorted
//Since, after each iteration rightmost i elements are array
sorted. System.out.println();
for (j = 0; j < n-i-1; j++) }
if (arr[j] > arr[j+1])
swap(&arr[j], &arr[j+1]); // Main method to test above
} public static void main(String args[])
// Function to print array. {
void display(int arr[], int size) Main ob = new Main();
{ int a[] = {64, 34, 25, 12, 22, 11, 90};
int i; ob.bubbleSort(a);//calling the bubbleSort function
for (i=0; i < size; i++) System.out.println("Sorted array");
cout<<arr[i]<<"\t"; ob.printArray(a); //calling the printArray function
cout<<endl; }
} }
//Main function to run the program.
int main() Output:
{ Before bubble sort
int array[] = {5, 3, 1, 9, 8, 2, 4,7}; 53198247
int size = sizeof(array)/sizeof(array[0]); After bubble sort:
cout<<"Before bubble sort: \n"; 12345789
display(array, size);//Calling display function to print
unsorted array.
bubbleSort(array, size);
cout<<"After bubble sort: \n";
display(array, size);//Calling display function to print
sorted array.
return 0;
}

Java Code

class Main
{
void bubbleSort(int a[])
{
int len = a.length; // calculating the length of array
for (int i = 0; i < len-1; i++)
for (int j = 0; j < len-i-1; j++) if (a[j] > a[j+1])
//comparing the pair of elements
{
// swaping a[j+1] and a[i]
Performance Based Analysis of Bubble Sort Algorithm
int temp = a[j];
Pros
a[j] = a[j+1];
1. Easy to implement
a[j+1] = temp;
2. Cool to implement
}
3. Gives the largest value of the array in the first iteration
}
itself.

12
4. Or the smallest value of array in the first iteration itself
(Minor tweak in implementation)
5. No demand for large amounts of memory for operation

😀
Cons
1. Noob (Bad) algorithm
2. Very horrible time complexity of O(n2)

Interesting Facts

1. Average and worst case time complexity: o(n2)


2. Best case time complexity: n when array is
already sorted.
3. Worst case: when the array is reverse sorted.

Chapter 5. Insertion Sort


Time Complexity For Bubble Sort
How Insertion Sort works
Best
In this technique we pick an Element and then insert it at
Ω(n) the appropriate position in ascending and descending
order.
Average
Insertion Sort
Θ(n2)
If we have an element then it requires a (n-1) pass to sort.
Worst In each pass we insert the current element at the appropriate
position so that the elements in current range are in order.
O(n2)
● In insertion sort A Sublist (or sorted array) is
maintained which is always sorted. This
algorithm is not suitable for large data sets.
● The average and worst complexity of an insertion
sort is O(n2).
● This is less efficient on a list containing more
numbers of elements.
● The main advantage of the insertion sort is
moderity.it is also exhibits a good performance.

13
for (i = 1; i < size; i++)
{
target = array[i];
Execution of Insertion Sort
j = i - 1;

Pass 1- First of all to give the unsorted array.In this array


/* Here the elements in b/w arrary[0 to i-1]
the first element should be fixed.so the compares second
which are greater than target are moved
and third element.In this array 5>2 then they are swapped .
ahead by 1 position each*/
while (j >= 0 && array[j] > target)
Pass 2- In this array algorithm compares the next two
{
elements and arranges the element with their position.
array[j + 1] = array[j];
j = j - 1;
Pass 3- the final array is Sorted.
}
array[j + 1] = target;
}
}

/* Function to print array */


void display(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}

// Main function to run the program


int main()
Algorithm of Insertion Sort {
int array[] = {5, 3, 1, 9, 8, 2, 4,7};
Insertion Sort-(A,N): A is an array with N elements. int size = sizeof(array)/sizeof(array[0]);

Step 1- I=1; printf("Before Insertion sort: \n");


display(array, size);
Step 2- Repeat Step 3 and 5 While I<N.
insertionSort(array, size);
Step 3-temp=A[I],J=I-1;
printf("After Insertion sort: \n");
Step 4-Repeat While J>=0 and temp<A[J] display(array, size);
return 0;
A[J+1]=A[J] and J=J-1 }

Step 5-A[j+1]=temp,I=I=1
C++ Code
Step 6-Exit #include <iostream>
using namespace std;
C code:-
//Function to print array.
#include <stdio.h> void display(int arr[], int size)
{
// Here we are implementing Insertion sort int i;
void insertionSort(int array[], int size) for (i=0; i < size; i++)
{ cout<< arr[i]<<"\t";
int i, target, j; cout<<"\n";

14
} {
int key = a[i];
//Main function to run the program. int j = i - 1;
int main()
{ /* Shift elements of a[0..i-1], that are
int array[] = {5, 3, 1, 9, 8, 2, 4,7}; greater than key, to one position ahead
int size = sizeof(array)/sizeof(array[0]); of their current position */
while (j >= 0 && a[j] > key)
cout<<"Before Insertion sort: \n"; {
display(array, size);//Using dispaly function to print a[j + 1] = a[j];
unsorted array. j = j - 1;
}
int i, target, j; a[j + 1] = key;
for (i = 1; i < size; i++) }
{ }
target = array[i];
j = i - 1; /* A utility function to print array of size n*/
static void printArray(int a[])
/* Here the elements in b/w arrary[0 to i-1] {
which are greater than target are moved int len = a.length;
ahead by 1 position each*/ for (int i = 0; i < len; ++i)
while (j >= 0 && array[j] > target) System.out.print(a[i] + " ");
{ System.out.println();
array[j + 1] = array[j]; }
j = j - 1; }
}
array[j + 1] = target; Output:
} Before Insertion sort:
cout<<"After Insertion sort: \n"; 53198247
display(array, size);//Using dispaly function to print After Insertion sort:
sorted array. 12345789
return 0;
} Advantages and Disadvantages of Insertion Sort
Advantages
Java Code
1. It is simple, small and easy to write.
// Java Code for implementation of Insertion Sort 2. It doesn’t use a lot of overhead.
class PrepInsta 3. It uses in place sorting, thus O(1) space
{ requirements
// Main method 4. If data is almost sorted, then it can be very fast
public static void main(String args[]) approaching O(n) and faster than Merge sort
{ (for sorted data, and small N, else merge sort is
int a[] = { 12,11,13,5,6 }; faster)
5. Efficient for (quite) small data sets.
PrepInsta ob = new PrepInsta();
ob.sort(a); Disadvantages

printArray(a); 1. Poor average time complexity of O(n2)


} 2. If there are many elements then it is inefficient
/*Function to sort array using insertion sort*/ 3. Many items needs to be shifted to one insertion
void sort(int a[])
{
Properties
int len = a.length;//calculating the length of the array
for (int i = 1; i < len; i++)

15
1. You will encounter the best case if the data is
already or nearly sorted
2. It will give worst case results if the array is sorted
in opposite order as required
Chapter 6. Selection Sort
Time Complexity For Insertion Sort
What is Selection
In this Sorting technique the list is divided into two parts.
Best The first one is the left end and the second one is the right
end . The selection Sort is a very simple sorting algorithm.
Ω(n)

Steps for Selection Sort in C


Average
There are the following Step of selection sort algorithms.

Θ(n2)
Step 1-Select the smallest value in the list.
Step 2-Swap smallest value with the first element of the
Worst list.
Step 3-Again select the smallest value in the list (exclude
O(n2) first value).
Step 4- Repeat above step for (n-1) elements until the list is
sorted.

Steps for Selection Sort in C


There are the following Step of selection sort algorithms.

Step 1-Select the smallest value in the list.


Step 2-Swap smallest value with the first element of the
list.
Step 3-Again select the smallest value in the list (exclude
first value).
Step 4- Repeat above step for (n-1) elements until the list is
sorted.

16
[End of Step 1 loop]

Implementation of Selection Sort 4-Exit.

We have been given an unsorted array. which we’ll make C Code:-


a sorted array using selection sort. first of all find the
smallest value in the array and then swap the smallest value // C program for implementation of selection sort
with the starting value. #include <stdio.h>

According to the image below, 8 is the smallest value in /* Display function to print values */
this array so 8 is swapped with the first element that is 72. void display(int array[], int size)
{
Similarly, in the next iteration we’ll find the next smallest int i;
value, excluding the starting value so in this array 10 is the for (i=0; i < size; i++)
second smallest value, which is to be swapped with 50. {
printf("%d ",array[i]);
These iterations will continue until we have the largest }
element to the right most end, along with all the other printf("\n");
elements in their correct position. }

And then we can finally say that the given array is // The main function to drive other functions
converted into a sorted array. int main()
{
int array[] = {5, 3, 1, 9, 8, 2, 4, 7};
int size = sizeof(array)/sizeof(array[0]);

printf("This is how array looks before sorting: \n");


display(array, size);

int i, j, min_idx,temp;

// Loop to iterate on array


for (i = 0; i < size-1; i++)
{
// Here we try to find the min element in array
min_idx = i;
for (j = i+1; j < size; j++)
Algorithm of selection sort {
if (array[j] < array[min_idx])
Algorithm SELECTION(A,N): This algorithm sorts the min_idx = j;
array A with N elements. }
// Here we interchange the min element with first one
1-[loop] temp = array[min_idx];
array[min_idx] = array[i];
Repeat Step 2 and 3 for K=0,1,2,..N-2: array[i] = temp;}
printf("This is how array looks after sorting: \n");
2-Call MIN(A,K,N) display(array, size);

3-[Interchange A[K] and A[LOC].] return 0;


}
Set TEMP=A[K],A[K]=A[LOC] and

A[LOC]=TEMP.

17
C++ Code:- // Main method, responsible for the execution of
the code
#include <iostream>
public static void main(String args[])
using namespace std;
{
//Display function to print values.
PrepInsta ob = new PrepInsta();
void display(int array[], int size)
int a[] = {19,17,25,43,15}; //initializing values to the
{
array
int i;
ob.sort(a); //calling sort method
for (i=0; i < size; i++)
System.out.println("Sorted array");
{
ob.printArray(a); //calling printArray method
cout<<array[i]<<"\t";
}
}
cout<<"\n";
void sort(int a[])
}
{
int len = a.length; //calculating the length of the
//The main function to drive other functions.
array
int main()
// One by one move boundary of unsorted subarray
{
for (int i = 0; i < len-1; i++)
int array[] = {5, 3, 1, 9, 8, 2, 4, 7};
{
int size = sizeof(array)/sizeof(array[0]);
// Find the minimum element in unsorted array
int min = i;
cout<<"Before sorting: \n";
for (int j = i+1; j < len; j++)
display(array, size);//Using dispaly function to print
if (a[j] < a[min])
unsorted array.
min = j;

int i, j, min_idx,temp;
// Swap the found minimum element with the first
element
//Loop to iterate elements of array.
int temp = a[min];
for (i = 0; i < size-1; i++)
a[min] = a[i];
{
a[i] = temp;
//Here we try to find the min element in the array.
}
min_idx = i;
}
for (j = i+1; j < size; j++)
{
// Prints the sorted array
if (array[j] < array[min_idx])
void printArray(int a[])
min_idx = j;
{
}
int len = a.length;
//Here we interchange the min element with the first
for (int i=0; i<len; ++i) //printing the sorted array
one.
System.out.print(a[i]+" ");
temp = array[min_idx];
System.out.println();
array[min_idx] = array[i];
}
array[i] = temp;}
cout<<"After sorting: \n";
display(array, size); //Using dispaly function to print
}
sorted array.

return 0;
Output
This is how array looks before sorting:
}
53198247
This is how array looks after sorting:
Java Code: 12345789
class PrepInsta
{ Performance

18
The Selection Sort best and worst case scenarios both
follow the time complexity format O(n^2) as the sorting Chapter 7. Merge Sort
operation involves two nested loops. The size of the array
again affects the performance.[1]
How Merge Sort Works
Strengths Merge Sort is an example of the divide and conquer
approach.It divides the array into equal halves and then
● The arrangement of elements does not affect its combines in a sorted manner.In merge sort the unsorted list
performance. is divided into N sublists, each having one element.
● Uses fewer operations, so where data movement 1. The complexity of the merge sort algorithm is O(NlogN)
is costly it is more economical where N is the number of elements to sort.
2. It can be applied to files of any size.
Weaknesses 3. In Merge sort all the elements are divided into two
sub-array again and again until one element is left.
● The comparisons within unsorted arrays requires 4. After the completion of the divide and conquer the
O(n^2) which is ideal where n is small elements are merged to make a sorted array .
5. This sorting is less efficient and it require more space as
Time Complexity For Selection Sort compare to other sorting,

Best

Ω(n2)

Average

Θ(n2)

Worst

O(n2)

Execution of Merge sort

This is an unsorted array and it will make a sorted array by


using a merge sort algorithm. In this array it will use the
divide technique . First of all the array will be divided into
N sub arrays. and the array divides until each has only one
element.

In this array each element should be divided into each


other.the sorted element will be merged by using conquer
technique. and the last element will be merged. And the
final array or list is sorted by using the merge sort
algorithm.

19
{
int i=strt,j=mid+1,p,index = strt;
int temp[10];

while(i<=mid && j<=end)


{
if(a[i]<a[j])
{
temp[index] = a[i];
i = i+1;
}
else
{
temp[index] = a[j];
C Code:- j = j+1;
#include <stdio.h> }

void mergeSort(int[],int,int); index++;


void merge(int[],int,int,int); }
if(i>mid)
void display(int arr[], int size){ {
int i; while(j<=end)
for(i = 0; i < size; i++){ {
printf("%d ",arr[i]); temp[index] = a[j];
} index++;
printf("\n"); j++;
} }
}
void main() else
{ {
int a[10]= {11, 9, 6, 19, 33, 64, 15, 75, 67, 88}; while(i<=mid)
int i; {
temp[index] = a[i];
int size = sizeof(a)/sizeof(a[0]); index++;
display(a, size); i++;
}
mergeSort(a,0,size-1); }
display(a, size); p = strt;
} while(p<index)
{
void mergeSort(int a[], int strt, int end) a[p]=temp[p];
{ p++;
int mid; }
if(strt<end) }
{
mid = (strt+end)/2; C++ Code:-
mergeSort(a,strt,mid); #include <iostream>
mergeSort(a,mid+1,end); using namespace std;
merge(a,strt,mid,end);
} void mergeSort(int[],int,int);
} void merge(int[],int,int,int);

void merge(int a[], int strt, int mid, int end) //Display function to print values.

20
void display(int arr[], int size) j = j+1;
{ }
int i;
for(i = 0; i < size; i++) index++;
{ }
cout<<arr[i]<<"\t"; if(i>mid)
} {
cout<<"\n"; while(j<=end)
} {
temp[index] = a[j];
int main() index++;
{ j++;
int a[10]= {8, 4, 5, 1, 3, 9, 0, 2, 7, 6}; }
int i; }
else
int size = sizeof(a)/sizeof(a[0]); {
cout<<"Before sorting: \n"; while(i<=mid)
display(a, size);//Using display function to print unsorted {
array. temp[index] = a[i];
cout<<"After sorting: \n"; index++;
mergeSort(a,0,size-1); i++;
display(a, size);//Using display function to print sorted }
array. }
} p = strt;
//Dividing the list into two sublist, sorting them and while(p<index)
merging them. {
void mergeSort(int a[], int strt, int end) a[p]=temp[p];
{ p++;
int mid; }
if(strt<end) }
{
mid = (strt+end)/2;
Java Code:-
mergeSort(a,strt,mid);//Divide //Java Program for Merge Sorting
mergeSort(a,mid+1,end);//Conqure public class Main {
merge(a,strt,mid,end);//Combine public static void display(int[] arr, int size) //this
} function display the array
} {
//Combining two sublist. for(int i = 0; i < size; i++) {
void merge(int a[], int strt, int mid, int end) System.out.print(arr[i] + " ");
{ }
int i=strt,j=mid+1,p,index = strt; System.out.println();
int temp[10]; }

while(i<=mid && j<=end) public static void main(String[] args) // main


{ function of the program
if(a[i]<a[j]) {
{ int[] a = {11, 9, 6, 19, 33, 64, 15, 75,
temp[index] = a[i]; 67, 88};
i = i+1; int i;
}
else int size = (int)a.length;
{ display(a, size);
temp[index] = a[j];

21
mergeSort(a, 0, size - 1); Merge Sort Advantages
display(a, size);
} 1. Fast ! Time complexity : O(N Log N)
2. Reliable, it gives same time complexity in all cases.
static void mergeSort(int[] a, int strt, int end) 3. Tim sort variant of this really powerful (Not important
//this function apply merging and sorting in the array for Placements)
{
int mid; Merge Sort Disadvantages
if(strt < end) 1. Space Complexity sucks !!!
{ 2. Space Complexity : O(n), most other algorithm have
mid = (strt + end) / 2; O(1)

mergeSort(a, strt, mid);


mergeSort(a, mid + 1, end); Time Complexity For Bubble Sort
merge(a, strt, mid, end);
} Best
}
Ω(nlogn)
static void merge(int[] a, int strt, int mid, int end)
//after sorting this function merge the array
Average
{
int i = strt, j = mid + 1, p, index = strt;
Θ(nlogn)
int[] temp = new int[10];

while(i <= mid && j <= end) { Worst


if(a[i] < a[j]) { temp[index] =
a[i]; i = i + 1; } else { temp[index] = a[j]; j = j + 1; } O(nlogn)
index++; } if(i > mid) {
while(j <= end) {
temp[index] = a[j];
index++;
j++;
}
} else {
while(i <= mid) {
temp[index] = a[i];
index++;
i++;
}
}
p = strt;
while(p < index) {
a[p] = temp[p];
p++;
}
}
}

Output
Input array - 11 9 6 19 33 64 15 75 67 88
Output array - 6 9 11 15 19 33 64 67 75 88

22
● If p < r then
Chapter 8. Quick Sort ● q= Partition (A, p, r)
● Quick Sort (A, p, q)
● Quick Sort (A, q + r, r)
How Quicksort works
Quick sort is an algorithm of the divide and conquer type.
That is,the problem of sorting a set is reduced to the Partition Algorithm
problem of sorting two smaller sets.
PARTITION (A, p, r)

How does it work? ● x ← A[p]


Quick sort works in the following way – ● i ← p-1
● j ← r+1
● Choose an item from array called as pivot ● while TRUE do
● Move all the elements smaller than pivot to left ● Repeat j ← j-1
partition ● until A[j] ≤ x
● Move all the elements greater than pivot to the ● Repeat i ← i+1
right partition. ● until A[i] ≥ x
● if i < j
Choose a new pivot item in each partition and keep doing ● then exchange A[i] ↔
the same process again until partitions of one element each ● A[j]
aren’t formed. ● else return j

How to choose Pivot?


These are the following ways you can choose pivot –

● First element as pivot.


● Last element as pivot (We use this in our
examples & Code)
● Random element as pivot.
● Median element as pivot.

Execution of quick sort


Quick sort works recursively, Partitioning moves all
smaller elements to left of pivot and greater to right side of
pivot, thus each time two sub array partitions are formed.
Thus again, we do partitioning in each of these sub arrays
individually.

Algorithm for quick sort in C++

23
}

//Recursive function to apply quickSort


void quickSort(int array[], int low, int high)
{
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
}
}

/* Function to display the array */


void display(int array[], int size)
C Code: {
int i;
#include<stdio.h>
for (i=0; i < size; i++)
printf("%d ", array[i]);
// A utility function to swap two elements
}
void swap(int* x, int* y)
{
//Main function to run the program
int temp = *x;
int main()
*x = *y;
{
*y = temp;
int array[] = {70, 90, 10, 30, 50, 20, 60};
}
int size = sizeof(array)/sizeof(array[0]);
quickSort(array, 0, size-1);
/* Partition function to do Partition
printf("Array after Quick Sorting: ");
elements on the left side of pivot elements would be
display(array, size);
smaller than pivot
return 0;
elements on the right side of pivot would be greater than
}
the pivot
*/
int partition (int array[], int low, int high) C++ Code:-
{
#include <iostream>
// pivot element selected as right most element in array
using namespace std;
each time
int pivot = array[high];
//Function to swap two elements.
int swapIndex = (low - 1); //swapping index
void swap(int* x, int* y)
{
for (int j = low; j <= high- 1; j++)
int temp = *x;
{
*x = *y;
// Check if current element is smaller than pivot
*y = temp;
element
}
if (array[j] < pivot)
{
/* Partition function to do Partition
swapIndex ++; // increment swapping index
elements on the left side of pivot elements would be
swap(&array[swapIndex], &array[j]);
smaller than pivot
}
elements on the right side of pivot would be greater than
}
the pivot
swap(&array[swapIndex + 1], &array[high]);
*/
return (swapIndex + 1);

24
int partition (int array[], int low, int high) return 0;
{ }
//Pivot element selected as right most element in array
each time.
Java Code:-
int pivot = array[high];
int swapIndex = (low - 1); //swapping index. /* Java program for Merge Sort */
public class MergeSort {
for (int j = low; j <= high- 1; j++) void merge(int arr[], int l, int m, int r)
{ {
//Check if current element is smaller than pivot int n1 = m - l + 1;
element. int n2 = r - m;
if (array[j] < pivot) int L[] = new int[n1];
{ int R[] = new int[n2];
swapIndex ++; //increment swapping index. for (int i = 0; i < n1; ++i)
swap(&array[swapIndex], &array[j]); L[i] = arr[l + i];
} for (int j = 0; j < n2; ++j)
} R[j] = arr[m + 1 + j];
swap(&array[swapIndex + 1], &array[high]); int i = 0, j = 0;
return (swapIndex + 1); int k = l;
} while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
//Recursive function to apply quickSort arr[k] = L[i];
void quickSort(int array[], int low, int high) i++;
{ }
if (low < high) else {
{ arr[k] = R[j];
/* indexPI is partitioning index, partition() function j++;
will }
return index of partition */ k++;
int indexPI = partition(array, low, high); }
while (i < n1) {
quickSort(array, low, indexPI - 1); //left partition arr[k] = L[i];
quickSort(array, indexPI + 1, high); //right partition i++;
} k++;
} }
while (j < n2) {
//Function to display the array arr[k] = R[j];
void display(int array[], int size) j++;
{ k++;
int i; }
for (i=0; i < size; i++) }
cout<< array[i]<<"\t"; void sort(int arr[], int l, int r)
} {
if (l < r) {
//Main function to run the program int m = (l + r) / 2;
int main() sort(arr, l, m);
{ sort(arr, m + 1, r);
int array[] = {7, 9, 1, 3, 5, 2, 6, 0, 4, 8}; merge(arr, l, m, r);
int size = sizeof(array)/sizeof(array[0]); }
cout<<"Before Sorting: \n"; }
display(array, size); static void printArray(int arr[])
quickSort(array, 0, size-1); {
cout<<"After Sorting: \n"; int n = arr.length;
display(array, size); for (int i = 0; i < n; ++i)

25
System.out.print(arr[i] + " ");
System.out.println();
}
public static void main(String args[])
{
int arr[] = { 12, 11, 13, 5, 6, 7 };

System.out.println("Given Array");
printArray(arr);

MergeSort ob = new MergeSort();


ob.sort(arr, 0, arr.length - 1); Chapter 9. Counting sort
System.out.println("\nSorted array");
Counting Sort, is an integer sorting algorithm, is a sorting
printArray(arr);
} technique in which we sort a collection of elements based
}
on numeric keys between the specific range. In the

counting algorithm we don’t compare elements while


Quick Sort Performance Analysis
sorting.it is often used as a subroutine in other sorting

Advantages algorithms. By counting It operates the no. of objects

1. As the name suggests !!! Is quick as a horse !! having each distinct key value, after this it performs some

arithmetic to calculate the position of each key value in the


2. Reliable algorithm and used a lot in industry
output sequence.
Disadvantages
It is used as a subroutine in another sorting algorithm for
● Needs additional spaces for temporary arrays,
thus space complexity is O(Log n) example radix sort. If we compare counting sort to bucket
● Very difficult to understand
sort then we see that bucket sort requires a large amount of
● It the first element is chosen as pivot by some
idiot then it causes worst case complexity of preallocated memory or linked list and dynamic array to
O(n2)
hold the sets of items within each bucket, whereas counting

sort instead stores a single number per bucket.

Time complexity of counting sort is O((n).

Algorithm of Counting Sort

Counting_Sort(A,B,K)

1-let C[0,k] be a new array

2- for i<-0 to k

3- C[i]<-0

26
4- for j<-1 to length[A] C[i]<-0

5- do C[A[j]] <- C[A[j]]+1 Step 2-

// C[i] now contains the number of elements equal to i. j=1 to 10 since,length[A]=10

6- for i<-1 to k C[A[j]]<-C[A[j]]+1

7-do C[i]<- C[i]+C[i-1] For j=1

// C[i] now contains the number of elements less than or C[A[1]]<-C[1]+1= 0+1 =1

equal to i.
C[1]<-1

8- for j<- length[A] down to 1


For j=2

9-do B[C[A[j]]]<- A[j]


C[A[2]]<-C[6]+1= 0+1 =1

10- C[A[j]]<-C[A[j]]-1.
C[6]<-1

similarly for j=5,6,7,8,9,10

Step 3-

For i= 1 to 6

C[i]<-C[i]+C[i-1]

For i=1

C[1]<-C[1]+C[0]

C[1]<-1+0 = 1

For i=2
Execution of Counting Sort

C[2]<-C[2]+C[1]
According to algorithm let us take an example

C[1]<-1+0 = 1
Step 1-

Similarly for i=4,5,6


i=0 to 6 since k=6(Largest element in array A)

27
Step 4- }
// function calling
counting_sort(a, k, n);
For j=10 to 1 printf("\n");
return 0;
B[C[A[j]]]<-A[j] }

C[A[j]]<-C[A[j]]-1 C++ code-

C code-
//sorting in c

//counting sort
#include
//function for counting sort
void counting_sort(int a[], int k, int n)
{
int i, j; #include <iostream>
int b[15], c[100]; using namespace std;
for (i = 0; i <= k; i++)
c[i] = 0; void countSort(int array[], int size)
for (j = 1; j <= n; j++) {
c[a[j]] = c[a[j]] + 1;
for (i = 1; i <= k; i++) int output[10];
c[i] = c[i] + c[i-1]; int count[10];
for (j = n; j >= 1; j--) int max = array[0];
{
b[c[a[j]]] = a[j]; //Find the largest element of the array
c[a[j]] = c[a[j]] - 1; for (int i = 1; i < size; i++)
} {
printf("The Sorted array is : "); if (array[i] > max)
// printing the output max = array[i];
for (i = 1; i <= n; i++) }
printf("%d ", b[i]);
} //Initializing count array with zeros.
/* End of counting_sort() */ for (int i = 0; i <= max; ++i)
// main function {
int main() count[i] = 0;
{ }
int n, k = 0, a[15], i;
printf("Enter the number of input : "); //Storing the count of each element
// user input for (int i = 0; i < size; i++) {
scanf("%d", &n); count[array[i]]++;
printf("\nEnter the elements to be sorted :\n"); }
for (i = 1; i <= n; i++)
{ //Storing the cumulative count of each array
scanf("%d", &a[i]); for (int i = 1; i <= max; i++) {
if (a[i] > k) { count[i] += count[i - 1];
k = a[i]; }
}

28
/*Finding the index of each element of the original array {
in count array, c[i] += c[i - 1];
and place the elements in output array*/ }
for (int i = size - 1; i >= 0; i--) { for (int i = arr.length - 1; i >= 0; i--)
output[count[array[i]] - 1] = array[i]; {
count[array[i]]--; output[c[arr[i] - min] - 1] = arr[i];
} c[arr[i] - min]--;
}

for (int i = 0; i < size; i++) { for (int i = 0; i < arr.length; i++)
array[i] = output[i]; {
} arr[i] = output[i];
} }
}
//printing function
void display(int array[], int size) static void display(int[] arr)
{ {
for (int i = 0; i < size; i++) for (int i = 0; i < arr.length; i++)
cout << array[i] << "\t"; {
cout << endl; System.out.print(arr[i] + " ");
} }
System.out.println("");
}
int main() public static void main(String[] args)
{ {
int array[] = {2, 5, 2, 8, 1, 4, 1}; int[] arr = {-4, -8, 0, -1, 8, 5, 1, 10};
int n = sizeof(array) / sizeof(array[0]); cSort(arr);
cout<<"Unsorted array\n"; display(arr);
display(array, n); }
countSort(array, n); }
cout<<"Sorted array\n"; Time Complexity
display(array, n);
} Best O(n + k)

Java code- Average O(n + k)

import java.util.*; Worst-O(n + k)

public class Main


{

static void cSort(int[] arr)


{
int max = Arrays.stream(arr).max().getAsInt();
int min = Arrays.stream(arr).min().getAsInt();
int range = max - min + 1;
int c[] = new int[range];
int output[] = new int[arr.length];
for (int i = 0; i < arr.length; i++)
{
c[arr[i] - min]++;
}

for (int i = 1; i < c.length; i++)

29
Chapter 10. Radix sort- Implementation of Radix sort

Let us take an example of radix sort

It is a sorting algorithm that is used to sort elements. Radix Given to a list ,the numbers would be sorted in three

sort is the method that many people begin to use when phases. the list is (248,140,261,323,438,120,221,443,266).

alphabetizing a large list of name or numeric


(A)- In the first phase, the once digits are sorted into a list..
number.Specifically ,
The numbers are collected box by box ,from pocket 8 to

The list of names is first sorted according to the first letter 0.(Note 261 will now be at the bottom of the pile and 438 at

of each name. That is, the names are arranged in 26 the top of the pile.) The cards are now rein put to the sorter.

classes,where the first class consist of those name that

begin with “A”, the second class consists of those name

that begin with “B”,and so on.During the second pass, each

class is alphabetized according to the second letter of the

name.And so on.

● The time complexity of Radix sort is O(kn) and


space complexity of Radix sort is O(k+n).the
running time of Radix appears to be better than
Quick Sort for a wide range of input numbers.

(B)- In the second phase, the tens digits are sorted into

pockets,Again the card are collected pocket by pocket and

rein put to the sorter.

30
2-use a stable sort to array A on digit i

//counting sort will do the job

The code for radix sort assumes that each element in the

n-element array A has d- digits,where digit 1 is the lowest

-order digit and d is the highest-order digit.

C code:

#include <stdio.h> //including library files


int max(int a[]); //declaring functions
void radix_sort(int a[]); //declaring functions
void main() //defining main()
{
In the last phase and third phase, we will notify that the int i;
int a[10]={92,106,365,90,33,19,72,56,45,12};
hundred digit are sorted into pockets. //initializing array with values
radix_sort(a);
printf("\n The sorted list is: \n"); //printing the sorted list
for(i=0;i<10;i++)
printf(" %d\t", a[i]);
}

int max(int a[]) //giving the definition to max()


{
int max=a[0], i; //finiding the largest number
for(i=1;i<10;i++)
{
if(a[i]>max)
max = a[i];
}
return max;
}
void radix_sort(int a[]) //providing definition to radix_sort
{
int bucket[10][10], bucket_count[10]; //declaring
variables
int i, j, k, remainder, NOP=0, divisor=1, max, pass;
//declaring variables
max = max(a);
So the final list is by ascending order to sorted digits or
while( max>0)
number is (120,140, 221,248,261,266,323,438,443) {
NOP++;
Algorithm of Radix sort max/=10;
}
for(pass=0;pass<NOP;pass++) // Initialization of the
buckets
1- for i<-1 to d do {

31
for(i=0;i<10;i++)
bucket_count[i]=0; for (int i = 0; i < max; ++i)
for(i=0;i<10;i++) count[i] = 0;
{
// sort the numbers according to the digit at passth //Calculate count of elements
place for (int i = 0; i < size; i++)
remainder = (a[i]/divisor)%10; count[(array[i] / place) % 10]++;
bucket[remainder][bucket_count[remainder]] = a[i];
bucket_count[remainder] += 1; //Calculating cumulative count
} for (int i = 1; i < max; i++)
// collect the numbers after PASS pass count[i] += count[i - 1];
i=0;
for(k=0;k<10;k++) //Placing the elements in sorted order
{ for (int i = size - 1; i >= 0; i--)
for(j=0;j<bucket_count[k];j++) {
{ output[count[(array[i] / place) % 10] - 1] = array[i];
a[i] = bucket[k][j]; count[(array[i] / place) % 10]--;
i++; }
}
} for (int i = 0; i < size; i++)
divisor *= 10; array[i] = output[i];
}
}
} //Main function to implement radix sort
void radixsort(int array[], int size)
{
C++ code //Getting maximum element
int max = getMax(array, size);

//Applying counting sort to sort elements based on place


value.
for (int place = 1; max / place > 0; place *= 10)
countSort(array, size, place);
}
#include <iostream>
using namespace std; //Printing an array
void display(int array[], int size)
//Function to get the largest element from an array {
int getMax(int array[], int n) int i;
{ for (i = 0; i < size; i++)
int max = array[0]; cout << array[i] << "\t";
for (int i = 1; i < n; i++) cout << endl;
if (array[i] > max) }
max = array[i];
return max; int main()
} {
int array[] = {112, 400, 543, 441, 678, 675, 9, 777};
//Using counting sort to sort the elements in the basis of int n = sizeof(array) / sizeof(array[0]);
significant places cout<<"Before sorting \n";
void countSort(int array[], int size, int place) display(array, n);
{ radixsort(array, n);
const int max = 10; cout<<"After sorting \n";
int output[size]; display(array, n);
int count[max]; }

32
// Change count[i] so that count[i] now
Output: contains
Before sorting // actual position of this digit in
112 400 543 441 678 675 output[]
9 777 for (i = 1; i < 10; i++)
After sorting count[i] += count[i - 1];
9 112 400 441 543 675
678 777 // Build the output array
for (i = len - 1; i >= 0; i--)
{
output[count[ (a[i]/exp)%10 ]
Java code-
- 1] = a[i];
//Radix sort Java implementation count[ (a[i]/exp)%10 ]--;
import java.io.*; }
import java.util.*;
// Copy the output array to arr[], so that
class PrepInsta arr[] now
{ // contains sorted numbers according to
/*Main Method to check for curent digit
above function*/ for (i = 0; i < len; i++)
>public static void main (String[] args) a[i] = output[i];
{ }
int a[] = {17, 45, 75, 90, 82,
24, 12, 60}; // The main function to that sorts arr[] of size n
int len = a.length; using
radixsort(a,len); // Radix Sort
print(a,len); static void radixsort(int a[], int len)
} {
// Find the maximum number to know
// A utility function to get maximum value in a[] number of digits
static int getMax(int a[], int n) int m = getMax(a, len);
{
int mx = a[0]; // Do counting sort for every digit. Note
for (int i = 1; i < len; i++) that instead
if (a[i] > mx) // of passing digit number, exp is
mx = a[i]; passed. exp is 10^i
return mx; // where i is current digit number
} for (int exp = 1; m/exp > 0; exp *= 10)
countSort(a, len, exp);
// A function to do counting sort of arr[] }
according to
// the digit represented by exp. // A utility function to print an array
static void countSort(int a[], int len, int exp) static void print(int a[], int len)
{ {
int output[] = new int[len]; // output for (int i=0; i<len; i++)
array System.out.print(a[i]+" ");
int i; }
int count[] = new int[10];
Arrays.fill(count,0); }
Time complexity of radix sort
// Store count of occurrences in count[] BEST- O(d(n + k))
for (i = 0; i < len; i++) Average- O(d(n + k))
count[ (a[i]/exp)%10 ]++; Worst- O(d(n + k))

33
3- do exchange A[1]<-> heap-size[A]-1
Chapter 11. Heap sort
4- heap-size[A]<-heap-size[A]-1
A heap is a complete binary tree which is represented using
5- MAX-HEAPIFY(A,1)
array or sequential representation.

BUILD-MAX-HEAP(A)
It is a special balanced binary tree data structure where the
1- heap-size[A]<-length[A]
root node is compared with its children and arranged

accordingly.Normally in max heap parent node always has 2- for i<-(length[A]/2) down to 1 do

a value greater than child node. 3- MAX-HEAPIFY(A,i)

The worst and Average complexity of heap sort is O(n Implementation of heap sort
As we know that heap sort is based on the tree structure.
log2 n).
so we will take an example of heap sort based on the tree.
● From the given array, build the initial max heap.
● Interchange the root element with the last Originally the given array is :[6,14,3,25,2,10,20,7,6]
element.
First we call Build-max heap
● Use repetitive downward operation from the root
node to rebuild the heap of size one less than the
heap size[A]=9
starting.
so,i=4 to 1, call MAX HEAPIFY (A,i)
Algorithm of heap sort
i.e., first we call MAX HEAPIFY (A,4)

MAX-HEAPIFY(A,i) A[l]=7, A[i]=A[4] = 25,A[r] = 6

1- i<-left[i] l<- left[4] = 8

2- r<-right[i] r<-right[4] = 9

3- if l<heap-size[A]and A[l]>A[i] 8<9 and 7>25 (false)

4- then largest<-1 Then,largest <-4

5- else largest<-i 9<9 and 6>25(false)

6- if r<heap-size[A] and A[r]>A[largest] Then,largest = 4

7- then largest<-r A[i]<-> A[4]

8- if largest!=i Now call MAX HEAPIFY (A,2)

9- then exchange A[i]<->A[largest] the A[length] =9

10- MAX-HEAPIFY[A,largest] So, i=A/2 = 9/2 =4

HEAP-SORT(A) i=4

1- BUILD-MAX-HEAP(A) since the parent node is greater than its child node.

2- for i<-length[A] down to 2

34
If the parent node is greater than the child node then the {
parent node replaces it with the lesser child node. int i;
for (i = size / 2 - 1; i >= 0; i--)
similarly for i=3,2,1 we get the following heap tree. heapify(arr, size, i);
for (i=size-1; i>=0; i--)
{
// swaping logic
temp = arr[0];
arr[0]= arr[i];
arr[i] = temp;
heapify(arr, i, 0);
}
}

void main() // defining main()


{
int arr[] = {58, 134, 3, 67, 32, 89, 15, 10,78, 9};
// array initializing with their elements.
int i;
int size = sizeof(arr)/sizeof(arr[0]);

heapSort(arr, size);

printf("printing sorted elements\n"); // printing the sorted


array
C code: for (i=0; i<size; ++i)
printf("%d\n",arr[i]);
#include<stdio.h> // including library files }
int temp;

void heapify(int arr[], int size, int i)//declaring functions


{
int max = i;
int left = 2*i + 1;
int right = 2*i + 2;
C++ code:
if (left < size && arr[left] >arr[max])
max= left;

if (right < size && arr[right] > arr[max])


max= right;

if (max!= i)
{
// performing sorting logic by using temporary variable
temp = arr[i];
arr[i]= arr[max];
arr[max] = temp;
heapify(arr, size, max);
} #include <iostream>
}
using namespace std;
void heapSort(int arr[], int size)// providing definition to
heap sort void heapify(int arr[], int n, int i)

35
{ int n = sizeof(arr)/sizeof(arr[0]);
int largest = i; cout << "Unsorted array \n";
int l = 2*i + 1; display(arr, n);
int r = 2*i + 2;
heapSort(arr, n);
//If left child is larger than root
if (l < n && arr[l] > arr[largest]) cout << "Sorted array \n";
largest = l; display(arr, n);
}
//If right child largest
if (r < n && arr[r] > arr[largest])
largest = r; Java code:
// Java program for implementation of Heap Sort
//If root is nor largest public class PrepInsta
if (largest != i) {
{ //Main() for the execution of the program
swap(arr[i], arr[largest]); public static void main(String args[])
{
//Recursively heapifying the sub-tree int a[] = {12, 11, 13, 5, 6, 7};
heapify(arr, n, largest); int len = a.length;
}
} PrepInsta ob = new PrepInsta();
ob.sort(a);
void heapSort(int arr[], int n)
{ System.out.println("Sorted array is");
printArray(a);
for (int i = n / 2 - 1; i >= 0; i--) }
heapify(arr, n, i); public void sort(int a[])
{
//One by one extract an element from heap int len = a.length;
for (int i=n-1; i>=0; i--)
{ // Build heap (rearrange array)
//Moving current root to end for (int i = len / 2 - 1; i >= 0; i--)
swap(arr[0], arr[i]); heapify(a, len, i);

//Calling max heapify on the reduced heap // One by one extract an element from heap
heapify(arr, i, 0); for (int i=len-1; i>=0; i--)
} {
} // Move current root to end
int temp = a[0];
//Function to print array a[0] = a[i];
void display(int arr[], int n) a[i] = temp;
{
for (int i = 0; i < n; i++) // call max heapify on the reduced heap
{ heapify(a, i, 0);
cout << arr[i] << "\t"; }
} }
cout << "\n";
} // To heapify a subtree rooted with node i which is
// an index in arr[]. n is size of heap
void heapify(int a[], int len, int i)
int main() {
{ int largest = i; // Initialize largest as root
int arr[] = {1, 14, 3, 7, 0}; int l = 2*i + 1; // left = 2*i + 1

36
int r = 2*i + 2; // right = 2*i + 2
Chapter 12. Stacks
// If left child is larger than root
if (l < len && a[l] > a[largest])
largest = l; Introduction to Stacks in Data Structures

Stack is one of the basic linear Data structures that we use


// If right child is larger than largest so far for storing our data. Data in a stack is stored in a serialized
if (r < len && a[r] > a[largest]) manner. One important thing about using a Stack is that the
largest = r; data first entered in the stack will be at the last of the stack.
This is one of the reasons why we also called Stack a LIFO
// If largest is not root Data Structure, i.e; Last in First Out. We’ll be discussing
if (largest != i) more about this feature later in this article.
{ Basic Terminology of Stack
int swap = a[i];
a[i] = a[largest];
Before we move on further with understanding the Stack
a[largest] = swap;
Data Structure, we need to learn about the basic
// Recursively heapify the affected sub-tree
heapify(a, len, largest); terminology that is associated with this data structure so
} that understanding stack will be a little easy for us.
}

/* A utility function to print array of size n */


static void printArray(int a[]) The basic terminology that we will be using in Stack is :
{
int len = a.length; 1. Top – This refers to the topmost element of the stack, or
for (int i=0; i<len; ++i)
in other words the element last entered in the stack.
System.out.print(a[i]+" ");
System.out.println(); 2. Push () – This is one of the operations that we can
}
perform on stack, for inserting data in this data structure.
} 3. Pop () – This operation deals with deleting the data from

Output: the stack. It deletes the top-most data from the stack.
Unsorted array
4. Peek () – This operation helps us in looking at the
1 14 3 7 0
Sorted array topmost element of the data without removing it from the
0 1 3 7 14
stack.

A stack may be implemented to have a bounded capacity. If


Time complexity of heap sort the stack is full and does not contain enough space for push

Best - O(nlogn) operation, the stack is then considered to be in an overflow


Average - O(nlogn) state.
Worst - O(nlogn)
Below is simple representation of a stack with push and

pop operations –

37
Applications of Stacks in Data Structures 3. Random access is not possible.
There are a lot of places where we use stack without even
4. Variable storage will be overwritten, which sometimes
realizing it. Let’s see some of the most common uses of
stack data structure. leads to undefined behavior of the function or program.

5. The stack will fall outside of the memory area, which


Real life examples of Stack
might lead to an abnormal termination.
1. Stacking up dishes after washing them.

2. Deck of cards Operations on Stack

3. Stacking a pile of boxes in our store rooms.

4. Libraries stack pile of books and articles.

Some Coding/Programming Applications of

Stack

1. Recursion

2. Backtrackking

3. Memory managament

4. Process Managament There are many operations that can be used to manipulate a

stack. A stack is a data structure in which the operations are

executed in constant time. There are a number of operations


Advantages of Using Stack over other data structures
that can be performed on a stack, but there are two major
1.Manages the data in a Last In First Out(LIFO) method
operations that are used to manipulate a stack.
which is not possible with Linked list and array.
These operations are:
2. When a function is called the local variables are stored in
1. Push()
a stack, and it is automatically destroyed once returned.
2. Pop()
3. A stack is used when a variable is not used outside that
Implementation of pop and push in C:
function.
#include<stdio.h>
4. It allows you to control how memory is allocated and

deallocated.

5. Stack automatically cleans up the object. #include<stdlib.h>

6. Not easily corrupted


#define size 10 //size of the stack
7. Variables cannot be resized.
int top_of_stack=-1,s[size];
Disadvantages of Using Stack over other data structures
void push();
1. Stack memory is very limited.
void pop();
2. Creating too many objects on the stack can increase the void show();

risk of stack overflow. void main()


{
int option;

38
{
while(1) printf("\nPopped element is:
{ %d",s[top_of_stack]);
printf("\nSelect from the following top_of_stack=top_of_stack-1;
options- "); }
}
printf("\n\n1.Push\n2.Pop\n3.Show\n4.Exit");
printf("\n\nEnter the operation you void show()
want to execute: "); {
scanf("%d",&option); int i;

switch(option) if(top_of_stack==-1)
{ {
case 1: push(); printf("\nStack is empty");
break; }
case 2: pop(); else
break; {
case 3: show(); printf("\nElements of the stack are:\n");
break; for(i = top_of_stack; i>=0; --i)
case 4: exit(0); printf("%d\n",s[i]);
}
default: printf("\nInvalid }
option. Please select a Valid operation");
} Infix Prefix Postfix Conversion (Stack)
}
}

void push()
{
int value;

if(top_of_stack == size-1)
{
printf("\nOperation failed. Stack is
full.");
}
else
{
printf("\nEnter the value you want to
push in the stack:");
scanf("%d",&value);
top_of_stack = top_of_stack + 1;
s[top_of_stack] = value;
} Introduction
}
● Operation : Any Expression of algebraic format
void pop() (Example : A + B)
{
if(top_of_stack == -1) ● Operands : A and B or 5 & 6 are operands
{
● Operators : +. -, %,*,/ etc are operators
printf("\nOperation failed. Stack is
empty");
}
else Infix Notation

39
Infix is the day to day notation that we use of format A + B

type. The general form can be classified as (a op b) where a

and b are operands(variables) and op is Operator.

● Example 1 : A + B

● Example 2 : A * B + C / D

Postfix Notation

Postfix is notation that compiler uses/converts to while

reading left to right and is of format AB+ type. The general

form can be classified as (ab op) where a and b are

operands(variables) and op is Operator.

● Example 1 : AB+

● Example 2 : AB*CD/+
Why are Postfix/Prefix Expressions faster than Infix?
For Infix Expression which is format A+B*C, if the
Prefix Notation
compiler is reading left to right then it can’t evaluate A+B
Prefix is notation that compiler uses/converts to while first until it has read whole expression and knows
reading right to left (some compilers can also read prefix expression is actually A + (B*C) i.e. B * C needs to be
left to right) and is of format +AB type. The general form implemented first
can be classified as (op ab) where a and b are
Postfix for above infix is ABC*+. Now, as soon as the
operands(variables) and op is Operator.
compiler sees two operands followed by an operator it can
● Example 1 : +AB implement it without caring for precedence.
● Example 2 : +*AB/CD
● Assume ABC*+

● ABC*+ (BC* is implemented as B*C and result

is put back)

● AX+ (Assuming X stores result of BC* i.e. B*C)

● Now finally AX+ can be implemented as A+X

Note
Compiler converts our Infix Expression into postfix or
Prefix as expressions are operated as stacks and postfix and
prefix are faster to implement as the compiler doesn't need
to care about precedence at all.

40
Compiler converts the infix expression to postfix/prefix at Else, Pop all the operators that have greater or equal
compile time, so at runtime your calculations are always
happening in post-prefix. A website's code may be precedence than the scanned operator. Once you pop them
compiled once a week but it may need to run 1 million
times a week. push this scanned operator. (If we see a parenthesis while
Which is why we prefer that runtime execution should be
as fast as possible. If calculations happen faster than we popping then stop and push scanned operator in the stack)
have optimized our page load time hugely right?
If the scanned character is an ‘(‘, push it to the stack.

Problem If the scanned character is an ‘)’, pop the stack and output it

until a ‘(‘ is encountered, and discard both the parenthesis.


● Infix: a + b * c + d can be written as a + (b * c) +
Now, we should repeat steps 2 – 6 until the whole infix i.e.
d
whole characters are scanned.
● Now, for all + – / * associativity is left to right we

will write it as Print output

● (a + (b * c)) + d and thus further ((a + (b * c)) + Do the pop and output (print) until stack is not empty

d)
Infix to Prefix
● Solving and converting innermost bracket to

postfix Problem (This is how to convert manually for MCQ


Question in the exam)
● Step 1 –((a + bc*)+ d)
● Infix: (a / b + c) - ( d + e * f) can be written as ((a
● Step 2 – Consider bc* as separate operand x the
/ b) + c) - ( d + (e * f))
innermost bracket now looks like ((a + x)+ d)
● Now, we have done the above according to
○ Applying postfix it looks like – (ax+ +
associativity
d)replacing x here (abc*+ + d)
● Solving and converting innermost bracket to
● Step 3 – Consideringabc*+as separate operand z,
prefix
the final bracket looks like – (z + d)the result
● Step 1 –(/ab + c) - ( d + *ef)
would be zd+
● Step 2 – Consider /ab and *ef as separate operand
○ replacing z value = abc*+d+
x and y

● the innermost bracket now looks like (x + c) - (d


Algorithm (For Code/Manual Calculation)
+ y)
First Start scanning the expression from left to right
○ Applying prefix it looks like – (+xc -
If the scanned character is an operand, output it, i.e. print it
+dy)replacing x and y here (+/abc -

Else +d*ef)

● Step 3 – Considering+/abc and+d*efas separate


If the precedence of the scanned operator is higher than the operand z and w, the final bracket looks like – (z
precedence of the operator in the stack(or stack is empty or - w)the result would be -zw
has'(‘), then push operator in the stack

41
○ replacing z and w value = -+/abc+d*ef

char pop()
Algorithm (For Code/Manual Calculation)
{

Given Infix - ((a/b)+c)-(d+(e*f)) if(top_of_stack == -1)

return -1;
Step 1: Reverse the infix string. Note that while reversing

the string you must interchange left and right parentheses. else

return s[top_of_stack--];
Step 2: Obtain the postfix expression of the expression
}
obtained from Step 1.

Step 3: Reverse the postfix expression to get the prefix


int precedence(char a)
expression
{

if(a == '(')
This is how you convert manually for theory question in the
exam return 0;

1. String after reversal – ))f*e(+d(-)c+)b/a(( if(a == '+' || a == '-')

2. String after interchanging right and left parenthesis – return 1;


((f*e)+d)-(c+(b/a))
if(a == '*' || a == '/')
3. Apply postfix – Below is postfix Reverse Postfix
return 2;
Expression
}
4. Final prefix: -+/abc+d*ef

Implementation of Infix expression to Postfix void main()


expression
{

char expression[20];
#include<stdio.h>
char *exp, a;
char s[100];
printf("Enter the expression you want to convert: ");
int top_of_stack = -1;
scanf("%s",expression);
void push(char a)
exp = expression;
{
while(*exp != '\0')
s[++top_of_stack] = a;
{
}
if(isalnum(*exp))

42
printf("%c",*exp); #include <stdlib.h>
#include <string.h>
else if(*exp == '(')
// A structure to represent a stack
push(*exp); struct Stack {
int top;
else if(*exp == ')') int maxSize;
// we are storing string in integer array, this will not give
{
error
// as values will be stored in ASCII and returned in
while((a = pop()) != '(')
ASCII thus, returned as string again
printf("%c", a); int* array;
};
}
struct Stack* create(int max)
else {
struct Stack* stack = (struct Stack*)malloc(sizeof(struct
{ Stack));
stack->maxSize = max;
while(precedence(s[top_of_stack]) >= stack->top = -1;
precedence(*exp)) stack->array = (int*)malloc(stack->maxSize *
sizeof(int));
printf("%c",pop());
return stack;
}
push(*exp);

} // Checking with this function is stack is full or not


// Will return true is stack is full else false
exp= exp + 1; //Stack is full when top is equal to the last index
int isFull(struct Stack* stack)
} {
if(stack->top == stack->maxSize - 1){
while(top_of_stack != -1) printf("Will not be able to push maxSize reached\n");
}
{ // Since array starts from 0, and maxSize starts from 1
return stack->top == stack->maxSize - 1;
printf("%c",pop()); }

}
// By definition the Stack is empty when top is equal to -1
// Will return true if top is -1
}
int isEmpty(struct Stack* stack)
{
return stack->top == -1;
}

// Push function here, inserts value in stack and increments


stack top by 1
Infix to postfix conversion code in C: void push(struct Stack* stack, int item)
{
// C Program for Implementation of stack (array) using if (isFull(stack))
structure return;
stack->array[++stack->top] = item;
}
#include <limits.h>
#include <stdio.h>

43
// Function to remove an item from stack. It decreases top
by 1 for (i = 0, j = -1; expression[i]; ++i)
int pop(struct Stack* stack) {
{ // Here we are checking is the character we scanned is
if (isEmpty(stack)) operand or not
return INT_MIN; // and this adding to to output.
return stack->array[stack->top--]; if (checkIfOperand(expression[i]))
} expression[++j] = expression[i];

// Function to return the top from stack without removing it // Here, if we scan character ‘(‘, we need push it to the
int peek(struct Stack* stack) stack.
{ else if (expression[i] == '(')
if (isEmpty(stack)) push(stack, expression[i]);
return INT_MIN;
return stack->array[stack->top]; // Here, if we scan character is an ‘)’, we need to pop
} and print from the stack
// do this until an ‘(‘ is encountered in the stack.
// A utility function to check if the given character is else if (expression[i] == ')')
operand {
int checkIfOperand(char ch) while (!isEmpty(stack) && peek(stack) != '(')
{ expression[++j] = pop(stack);
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= if (!isEmpty(stack) && peek(stack) != '(')
'Z'); return -1; // invalid expression
} else
pop(stack);
// Fucntion to compare precedence }
// If we return larger value means higher precedence else // if an operator
int precedence(char ch) {
{ while (!isEmpty(stack) &&
switch (ch) precedence(expression[i]) <= precedence(peek(stack)))
{ expression[++j] = pop(stack);
case '+': push(stack, expression[i]);
case '-': }
return 1;
}
case '*':
case '/': // Once all initial expression characters are traversed
return 2; // adding all left elements from stack to exp
while (!isEmpty(stack))
case '^': expression[++j] = pop(stack);
return 3;
} expression[++j] = '\0';
return -1; printf( "%s", expression);
} }

// The driver function for infix to postfix conversion int main()


int covertInfixToPostfix(char* expression) {
{ char expression[] = "((a+(b*c))-d)";
int i, j; covertInfixToPostfix(expression);
return 0;
// Stack size should be equal to expression size for safety }
struct Stack* stack = create(strlen(expression));
if(!stack) // just checking is stack was created or not
return -1 ;

44
Infix to prefix conversion code in C: // Will return true is stack is full else false

#include <limits.h> //Stack is full when top is equal to the last index

#include <stdio.h> int isFull(struct Stack* stack)

#include <stdlib.h> {

#include <string.h> if(stack->top == stack->maxSize - 1){

printf("Will not be able to push maxSize reached\n");

// A structure to represent a stack }

struct Stack { // Since array starts from 0, and maxSize starts from 1

int top; return stack->top == stack->maxSize - 1;

int maxSize; }

// we are storing string in integer array, this will not give // By definition the Stack is empty when top is equal to -1
error
// Will return true if top is -1
// as values will be stored in ASCII and returned in ASCII
thus, returned as string again int isEmpty(struct Stack* stack)

int* array; {

}; return stack->top == -1;

struct Stack* create(int max)

{ // Push function here, inserts value in stack and increments


stack top by 1
struct Stack* stack = (struct Stack*)malloc(sizeof(struct
Stack)); void push(struct Stack* stack, int item)

stack->maxSize = max; {

stack->top = -1; if (isFull(stack))

stack->array = (int*)malloc(stack->maxSize * return;


sizeof(int));
stack->array[++stack->top] = item;
return stack;
}
}

// Function to remove an item from stack. It decreases top


// Checking with this function is stack is full or not by 1

45
int pop(struct Stack* stack)

{ case '*':

if (isEmpty(stack)) case '/':

return INT_MIN; return 2;

return stack->array[stack->top--];

} case '^':

// Function to return the top from stack without removing it return 3;

int peek(struct Stack* stack) }

{ return -1;

if (isEmpty(stack)) }

return INT_MIN;

return stack->array[stack->top]; // The driver function for infix to postfix conversion

} int getPostfix(char* expression)

// A utility function to check if the given character is {


operand
int i, j;
int checkIfOperand(char ch)
// Stack size should be equal to expression size for safety
{
struct Stack* stack = create(strlen(expression));
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
if(!stack) // just checking is stack was created or not
}
return -1 ;
// Fucntion to compare precedence

// If we return larger value means higher precedence


for (i = 0, j = -1; expression[i]; ++i)
int precedence(char ch)
{
{
// Here we are checking is the character we scanned is
switch (ch) operand or not

{ // and this adding to to output.

case '+': if (checkIfOperand(expression[i]))

case '-': expression[++j] = expression[i];

return 1;

46
// Here, if we scan character ‘(‘, we need push it to the expression[++j] = pop(stack);
stack.

else if (expression[i] == '(')


expression[++j] = '\0';
push(stack, expression[i]);
}

void reverse(char *exp){


// Here, if we scan character is an ‘)’, we need to pop
and print from the stack

// do this until an ‘(‘ is encountered in the stack. int size = strlen(exp);

else if (expression[i] == ')') int j = size, i=0;

{ char temp[size];

while (!isEmpty(stack) && peek(stack) != '(') temp[j--]='\0';

expression[++j] = pop(stack); while(exp[i]!='\0')

if (!isEmpty(stack) && peek(stack) != '(') {

return -1; // invalid expression temp[j] = exp[i];

else j--;

pop(stack); i++;

} }

else // if an opertor strcpy(exp,temp);

{ }

while (!isEmpty(stack) && void brackets(char* exp){


precedence(expression[i]) <= precedence(peek(stack)))
int i = 0;
expression[++j] = pop(stack);
while(exp[i]!='\0')
push(stack, expression[i]);
{
}
if(exp[i]=='(')

exp[i]=')';
}
else if(exp[i]==')')
// Once all inital expression characters are traversed
exp[i]='(';
// adding all left elements from stack to exp
i++;
while (!isEmpty(stack))

47
} Introduction to stack

} More about Stacks


1. Stack can be defined as a Data Structure that serves as
void InfixtoPrefix(char *exp){
saving the data in a particular fashion.
int size = strlen(exp);
2. In linear data structures like an array and linked list a
// reverse string user is allowed to insert or delete any element to and from

reverse(exp); any location respectively.

3. However, in a Stack, both, insertion and deletion, is


//change brackets
permitted at one end only.
brackets(exp);
4. A Stack works on the LIFO (Last In – First Out) basis,
//get postfix i.e, the first element that is inserted in the stack would be

getPostfix(exp); the last to be deleted; or the last element to be inserted in

the stack would be the first to be deleted.


// reverse string again

reverse(exp);
Stack Operations
}
Push: Adding a new item to the Stack Data Structure,
int main()
in other words pushing new item to Stack DS.

{
If Stack is full, then it is said to be in an overflow condition
printf("The infix is: ");

char expression[] = "((a/b)+c)-(d+(e*f))"; Pop: Removing an item from the stack, i.e. popping an

item out.
printf("%s\n",expression);

InfixtoPrefix(expression); If a stack is empty then it is said to be in an underflow

condition
printf("The prefix is: ");

printf("%s\n",expression); 1. Peek: This basically returns the topmost item in the

return 0; stack, in other words, peek what is the topmost item.

2. IsEmpty: This returns True If the stack is empty else


}
returns False
Output –

The Infix is: ((a/b)+c)-(d+(e*f))

The prefix is: -+/abc+d*ef

48
2. Pop()
Representation of stack.
Stack as a data structure can be represented in two ways.
● When we require to remove an element to the

● Stack as an Array. stack we perform Pop() operation.

● Stack as a struct ● Pop() operation is synonymous of deletion in a

● Stack as a Linked List. data structure.

Operations on a Stack
There are a number of operations we can perform on a

stack as per our need which are as follows:

● Push().

● Pop().

● Top/Peak().

● isEmpty().

The time complexity of each of these operations is constant 3. Top()


time, i.e , O(1).

● This operation returns the top most or peak


1. Push()
element of the stack.

● When we require to add an element to the stack ● The value of top changes with each push() or

we perform Push() operation. pop() operation.

● Push() operation is synonymous of insertion in a

data structure.

49
1. When we initialise the stack, there is no element in a

stack so, Top value is initialised to Top = -1

2. The value is -1 as if using an array to implement a stack

if there is 1 element the location would be a[0], thus, for no

element we use – 1.

3. Push: on pushing new element the Top value increments

by 1, top++

4. Pop: on popping a new element the top value decrements

by 1, top–

5. Before pushing we check if the stack is full or not

6. Before popping we check if the stack is empty or not

Code for stack using structure in C:


4. isEmpty()

● This operation returns true if the stack is found to


// C Program for Implementation of stack (array) using
be empty. structure
#include <limits.h>
● Empty stack symbolizes that top = -1.
#include <stdio.h>
#include <stdlib.h>

// A structure to represent a stack


struct Stack {
int top;
int maxSize;
int* array;
};

struct Stack* create(int max)


{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct
Stack));
stack->maxSize = max;
stack->top = -1;
stack->array = (int*)malloc(stack->maxSize *
sizeof(int));
//here above memory for array is being created
// size would be 10*4 = 40
return stack;
}

How does the stack work? // Checking with this function is stack is full or not
// Will return true is stack is full else false
● Top: An integer variable Top is used, to keep //Stack is full when top is equal to the last index
int isFull(struct Stack* stack)
track of topmost element in the stack {
if(stack->top == stack->maxSize - 1){

50
printf("Will not be able to push maxSize reached\n"); else
} printf("Can't Pop stack must be empty\n");
// Since array starts from 0, and maxSize starts from 1
return stack->top == stack->maxSize - 1; printf("Do you want to Pop again? Yes: 1 No: 0\n");
} scanf("%d",&flag);
}
// By definition the Stack is empty when top is equal to -1 return 0;
// Will return true if top is -1 }
int isEmpty(struct Stack* stack)
{ O/P
return stack->top == -1;
} We have pushed 5 to stack
We have pushed 10 to stack
// Push function here, inserts value in stack and increments We have pushed 15 to stack
stack top by 1 We have popped 15 from the stack
void push(struct Stack* stack, int item) Do you want to Pop again? Yes: 1 No: 0
{ 0
if (isFull(stack))
return; Code in C++:
stack->array[++stack->top] = item;
printf("We have pushed %d to stack\n", item); #include <bits/stdc++.h>
} using namespace std;

// Function to remove an item from stack. It decreases top


by 1 struct Node {
int pop(struct Stack* stack) int data;
{ Node *next = NULL;
if (isEmpty(stack)) };
return INT_MIN; class Stack {
return stack->array[stack->top--]; Node *top = NULL;
} public:
void push(); // Used to push element
// Function to return the top from stack without removing it void pop(); // Used to pop element
int peek(struct Stack* stack) void diplay(); // Used to display the stack
{ ~Stack(); // Used to remove the memory
if (isEmpty(stack)) };
return INT_MIN; void Stack::push() {
return stack->array[stack->top]; Node *temp = new Node; // Creating New node
} cout << “Enter Data: “;
int value;
int main() cin >> value;
{ temp -> data = value; // Adding value
struct Stack* stack = create(10); temp -> next = top; // Pointing to top
top = temp; // Changing top to current element
push(stack, 5); }
push(stack, 10); void Stack::pop() {
push(stack, 15); if (top == NULL) { // Check whether empty or not
cout <<“Stack Empty\n“;
int flag=1; }
while(flag) else {
{ Node *temp = top;
if(!isEmpty(stack)) cout << temp -> data << ” deleted\n“; // Data Deleted
printf("We have popped %d from stack\n", top = top -> next; // Changing top to next element
pop(stack)); delete temp; // Deleting the memory

51
} 1. P for push operation
} 2. R for pop operation
void Stack::diplay() { 3. D for display operation
Node *temp = top; 4. Q to quit
while (temp != NULL) { // Printing until encounter R
NULL position 21 deleted
cout << temp -> data << ” “; Enter
temp = temp -> next; 1. P for push operation
} 2. R for pop operation
cout << endl; 3. D for display operation
} 4. Q to quit
Stack::~Stack() { // Destructor Called to delete data P
Enter Data: 11
while (top != NULL) { Enter
Node *temp = top; 1. P for push operation
cout << temp -> data << ” deleted\n”; 2. R for pop operation
top = top -> next; 3. D for display operation
delete temp; 4. Q to quit
} D
} 11 20
int main() { Enter
Stack st; 1. P for push operation
char ch; 2. R for pop operation
do { 3. D for display operation
cout <<“Enter \n“; 4. Q to quit
cout << “1. P for push operation\n“; Q
cout << “2. R for pop operation\n“; 11 deleted
cout << “3. D for display operation\n“; 20 deleted
cout << “4. Q to quit\n“;
cin >> ch;
switch(ch) {
Code in java:
case ‘P’ : st.push(); break;
case ‘R’ : st.pop(); break;
/* Java program to implement stack
case ‘D’ : st.diplay(); break;
operations using array*/
}
class Stack {
}while (ch != ‘Q’);
static int MAX = 100;
return 0;
int top;
}
int a[] = new int[MAX]; // Maximum size of Stack
Output:
Enter
1. P for push operation
boolean isEmpty()
2. R for pop operation
{
3. D for display operation
return (top < 0);
4. Q to quit
}
P
Stack()
Enter Data: 20
{
Enter
top = –1;
1. P for push operation
}
2. R for pop operation
3. D for display operation
4. Q to quit
boolean push(int x)
P
{
Enter Data: 21
if (top >= (MAX – 1)) {
Enter
System.out.println(“Overflow condition reached”);

52
return false; stacknode node;
}
else { static class stacknode {
a[++top] = x; int data;
System.out.println(x + ” pushed into stack”); stacknode next;
return true;
} stacknode(int data) { this.data = data; }
} }

public boolean isEmpty()


int pop() {
{ if (node == null) {
if (top < 0) { return true;
System.out.println(“Underflow condition reached”); }
return 0; else
} return false;
else { }
int x = a[top–];
return x; public void push(int data)
} {
} stacknode newNode = new stacknode(data);

if (node == null) {
int peek() node = newNode;
{ }
if (top < 0) { else {
System.out.println(“Underflow condition”); stacknode temp = node;
return 0; node = newNode;
} newNode.next = temp;
else { }
int x = a[top]; System.out.println(data);
return x; }
}
} public int pop()
} {
class Prepinsta { int popped = Integer.MIN_VALUE;
public static void main(String args[]) if (node == null) {
{ System.out.println(“Stack is Empty”);
Stack stk = new Stack(); }
stk.push(20); else {
stk.push(40); popped = node.data;
stk.push(60); node = node.next;
System.out.println(stk.pop()); }
} return popped;
} }

public int peek()


Java code to implement stack using {
linked list : if (node == null) {
System.out.println(“Stack is empty”);
// Java Code for Linked List Implementation return Integer.MIN_VALUE;
}
public class LinkedList { else {
return node.data;

53
} Despite the difference, an array can be used to represent a
}
stack by taking an array of maximum size; big enough to

manage a stack.
public static void main(String[] args)
{

LinkedList sll = new LinkedList();

slk.push(20);
slk.push(40);
slk.push(60);

System.out.println(slk.pop());

System.out.println(“Top element is “ + slk.peek());


}
} Step 1:
Output :

60
● Push (40).
Time complexity ● Top = 40

Push- O(1) ● Element is inserted at a[5].


Pop - O(1)
Display - O(n)
Space complexity - O(n)

Representation of stack as array


A stack is a data structure that can be represented as an

array. Let us learn more about Array representation of a

stack –

Step 2:
An array is used to store an ordered list of elements. Using

an array for representation of stack is one of the easy


● Push (18).
techniques to manage the data. But there is a major
● Top = 18
difference between an array and a stack.
● Element is inserted at a[4].
● Size of an array is fixed.

● While, in a stack, there is no fixed size since the

size of stack changed with the number of

elements inserted or deleted to and from it.

54
Step 5:

● Push (08).

● Top = 08

● Element is inserted at a[1].

Step 3:
Step 6:

● Push (33).

● Top = 33 ● Push (12).

● Element is inserted at a[3]. ● Top = 12

● Element is inserted at a[0].

Step 4:

● Push (21).

● Top = 21

● Element is inserted at a[2].

Step 7:

● Top = -1.

● End of array.

55
default:
printf("\nPlease enter a correct option\n");
break;
}
}

Code in C(using array): void Push(int stack[],int num)


{
#include <stdio.h> if(top_of_stack==size-1)
#include <stdlib.h> {
printf("\nCannot add element, Stack is full\n");
#define size 20 return;
}
int stack[size],top_of_stack; top_of_stack++;
stack[top_of_stack]=num;
void Push(int [],int); //to insert elements in the stack }

void Pop (int []);//to delete elements from the stack void Pop(int stack[])
{
void display(int []); //to display the elements int del_num;
if(top_of_stack==-1)
void main() {
{ printf("Empty Stack.\n");
int num=0; return;
int option=0; }
top_of_stack=-1;
del_num=stack[top_of_stack];
while(1) top_of_stack--;
{ printf("Element deleted: %d \n",del_num);
printf("\n 1: Push \n 2: Pop \n 3: Display \n 4: Exit \n return;
Enter one of your choices: "); }
scanf("%d",&option);
void display(int stack[])
switch(option) {
{ int i=0;
case 1: if(top_of_stack==-1)
printf("Enter the item you want to insert :"); {
scanf("%d",&num); printf("Empty Stack .\n");
Push(stack,num); return;
break; }

case 2: printf("Top of stack is: \n%d ",stack[top_of_stack]);


Pop(stack); for(i = top_of_stack ; i >=0 ; i--)
break; {
printf(" %d ",stack[i]);
case 3: }
display(stack); printf("\n\n");
break; }
O/P
case 4: 1: Push
exit(0); 2: Pop

56
3: Display {
4: Exit return (top < 0);
}
Enter one of your choices: 1 Stack()
Enter the item you want to insert :1 {
1: Push top = –1;
2: Pop }
3: Display
4: Exit
boolean push(int x)
Enter one of your choices: 1 {
Enter the item you want to insert :2 if (top >= (MAX – 1)) {
1: Push System.out.println(“Overflow condition reached”);
2: Pop return false;
3: Display }
4: Exit else {
Enter one of your choices: 1 a[++top] = x;
System.out.println(x + ” pushed into stack”);
Enter the item you want to insert :3 return true;
}
1: Push }
2: Pop
3: Display
4: Exit int pop()
Enter one of your choices: 2 {
if (top < 0) {
Element deleted: 3 System.out.println(“Underflow condition reached”);
1: Push return 0;
2: Pop }
3: Display else {
4: Exit int x = a[top–];
Enter one of your choices: 3 return x;
}
Top of stack is: }
2 1

1: Push int peek()


2: Pop {
3: Display if (top < 0) {
4: Exit System.out.println(“Underflow condition”);
Enter one of your choices: 4 return 0;
}
else {
Code in java(using array): int x = a[top];
return x;
}
/* Java program to implement stack
}
operations using array*/
}
class Stack {
class Prepinsta {
static int MAX = 100;
public static void main(String args[])
int top;
{
int a[] = new int[MAX]; // Maximum size of Stack
Stack stk = new Stack();
stk.push(20);
stk.push(40);
boolean isEmpty()

57
stk.push(60); But performing the operations at the beginning occurs in
System.out.println(stk.pop());
} constant time. Let us understand this with the help of an
} example.
Output :
Let us consider a linked list as shown here.
60

In the given data we can see that we have-


Representation of stack as linked list
First, we have to understand what a linked list is, to ● Head = 200.

understand linked list representation of a stack. A Linked ● Top = 33.

List is a Data Structure which consists of two parts:

● The data/value part.


● The pointer which gives the location of the next
node in the list.

Stack can also be represented by using a linked list. We

know that in the case of arrays we face a limitation , i.e ,

array is a data structure of limited size. Hence before using

an array to represent a stack we will have to consider an

enough amount of space to suffice the memory required by

the stack. Push / Pop At the end Of a Linked List

Consider the Linked List as shown above. Now if we want

to push/pop a node at the end, we have to traverse all the n

number of nodes, until we reach the end of the linked list.

We traverse the whole list from the beginning to the end.

However, a Linked List is a much more flexible data

structure. Both the push and pop operations can be

performed on either ends.. But We prefer performing the

Push and pop operation at the beginning. The Stack

operations occur in constant time. But if we perform the

push and pop operations at the end of the linked list it takes

time O(n).

58
● Now if we want to insert a node at the end of the The time complexity of inserting a new node at the

linked list, we traverse from the first node to the beginning of the linked list is O(1).

second node to the last node. Let us consider the previous example only. We are given a

● We find the end of the list where the node points Linked List as follows:

to the null and the node to be inserted is as shown

here.

A new node to be inserted to the Linked List is shown

here.
● The new node is pushed at the end of the list.
The new node 40 is to be inserted at the beginning of the
● The second last node , i.e, 08 now points to the
list.
location of the last node.

● The newly inserted node at the end now points to

null.

● The new node is inserted at the beginning where

we have just a single traversal after spotting the

head of the Linked List.


Push / Pop operation at the beginning of the
● The value of head changes from 200 to 100.
Linked List
● The pointer of the new node stores the address of

the next node.


Pushing a new node at the beginning of a linked list takes
● The final linked list is shown here.
place in constant time. When inserting the new node the

number of traversals that occur is equal to 1. So it is much

faster than the previous method of insertion

59
case 3:
{
display();
break;
}
case 4:
{
printf("Exit");
break;
}
default:
{
printf("\nKindly enter a valid option\n");
}
Code in C(using linked list) };
}
}
#include <stdio.h> void Push ()
#include <stdlib.h> {
int element;
void Push(); /*to insert the element*/ struct n *ptr = (struct n*)malloc(sizeof(struct n));
if(ptr == NULL)
void pop(); /*to delete the element*/ {
printf("Stack full. Operation failed");
void display(); /*to display the elements in a stack*/ }
else
struct n {
{ printf("Enter the element you want to insert: ");
int element; scanf("%d",&element);
struct n *nxt; if(hd==NULL)
}; {
struct n *hd; ptr->element = element;
ptr -> nxt = NULL;
void main () hd=ptr;
{ }
int option=0; else
while(option != 4) {
{ ptr->element = element;
printf("\nSelect from the following ptr->nxt = hd;
options\n1.Push\n2.Pop\n3.Show\n4.Exit \nEnter one of hd=ptr;
your choices:");
scanf("%d",&option); }
switch(option) printf("Element is inserted");
{
case 1: }
{ }
Push();
break; void pop()
} {
case 2: int num;
{ struct n *ptr;
pop(); if (hd == NULL)
break; {
} printf("Not enough elements. Underflow!");

60
} }
else
{ public void push(int data)
num = hd->element; {
ptr = hd; stacknode newNode = new stacknode(data);
hd = hd->nxt;
free(ptr); if (node == null) {
printf("Element deleted: %d",num); node = newNode;
}
} else {
} stacknode temp = node;
void display() node = newNode;
{ newNode.next = temp;
int i; }
struct n *ptr; System.out.println(data);
ptr=hd; }
if(ptr == NULL)
{ public int pop()
printf("The stack is empty\n"); {
} int popped = Integer.MIN_VALUE;
else if (node == null) {
{ System.out.println(“Stack is Empty”);
printf("The stack elements are as follows: \n"); }
while(ptr!=NULL) else {
{ popped = node.data;
printf("%d\n",ptr->element); node = node.next;
ptr = ptr->nxt; }
} return popped;
} }
}
public int peek()
{
Code in java(using linked list) if (node == null) {
System.out.println(“Stack is empty”);
return Integer.MIN_VALUE;
// Java Code for Linked List Implementation
}
else {
public class LinkedList {
return node.data;
}
stacknode node;
}

static class stacknode {


int data;
public static void main(String[] args)
stacknode next;
{

stacknode(int data) { this.data = data; }


LinkedList sll = new LinkedList();
}
slk.push(20);
public boolean isEmpty()
slk.push(40);
{
slk.push(60);
if (node == null) {
return true;
System.out.println(slk.pop());
}
else
System.out.println(“Top element is “ + slk.peek());
return false;

61
} Steps to convert
}
Output :
Any infix op1 oper op2 can be written as op1 op2 oper
Top element is 60 Where op1 = Operand 1

op2 = Operand2
Infix To Postfix Conversion using Stack oper = Operation

Any operation can be expressed in Infix, postfix and prefix, Example a + b can be written as ab+ in postfix
we shall see how to convert infix to prefix operation via
manual calculation and via code.
Problem

Overview
1. Infix: a + b * c + d can be written as a + (b * c) + d
2. Now, for all + – / * associativity is left to right we will
● Infix – Any operation of format a op b format
write it as
example a + b is called an infix operation
3. (a + (b * c)) + d and thus further ((a + (b * c)) + d)
● Postfix – An operation or expression can also be
4. Solving and converting innermost bracket to postfix
written in the format of a b op i.e. a b + which is
Step 1 –((a + bc*)+ d)
similar to writing a + b in infix. All we are doing
Step 2 – Consider bc* as separate operand x the innermost
is shifting operator to the right of operands
bracket now looks like ((a + x)+ d)

Applying postfix it looks like – (ax+ + d)replacing x here

(abc*+ + d)
Why do we need a postfix operator?
Step 3 – Consideringabc*+as separate operand z, the final

For a compiler, it is easier to read postfix or prefix bracket looks like – (z + d)the result would be zd+

operations. As a compiler either reads from right to left or replacing z value = abc*+d+

left to right. Let us understand this with the help of an Algorithm


example –
1. First Start scanning the expression from left to right
1. Let us assume compiler starts reading from right to left
2. If the scanned character is an operand, output it, i.e. print
2. It reads c + d the operation first and it would be efficient
it
if it could’ve implemented it, but, it can’t as next operation
3. Else
is c * b which has higher precedence and must be
*If the precedence of the scanned operator is higher than
implemented first.
the precedence of the operator in the stack(or stack is
3. Thus, if the compiler reads a notation in which, it can
empty or has'(‘), then push operator in the stack
keep on implementing operations as soon as it sees them
*Else, Pop all the operators that have greater or equal
right!
precedence than the scanned operator. Once you pop them

push this scanned operator. (If we see a parenthesis while


The corresponding Postfix would be: abc*+d+ popping then stop and push scanned operator in the stack)

62
1. If the scanned character is an ‘(‘, push it to the stack.

2. If the scanned character is an ‘)’, pop the stack and

output it until a ‘(‘ is encountered, and discard both the

parenthesis.

3. Now, we should repeat the steps 2 – 6 until the whole

infix i.e. whole characters are scanned.

4. Print output

5.Do the pop and output (print) until stack is not empty

Program for Infix to Postfix in C

// C Program for Implementation of stack (array) using


structure

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// A structure to represent a stack


struct Stack {
int top;
int maxSize;
// we are storing string in integer array, this will not give
error

63
// as values will be stored in ASCII and returned in ASCII int peek(struct Stack* stack)
thus, returned as string again {
int* array; if (isEmpty(stack))
}; return INT_MIN;
return stack->array[stack->top];
struct Stack* create(int max) }
{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct // A utility function to check if the given character is
Stack)); operand
stack->maxSize = max; int checkIfOperand(char ch)
stack->top = -1; {
stack->array = (int*)malloc(stack->maxSize * return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
sizeof(int)); }
return stack;
} // Function to compare precedence
// If we return larger value means higher precedence
// Checking with this function is stack is full or not int precedence(char ch)
// Will return true is stack is full else false {
//Stack is full when top is equal to the last index switch (ch)
int isFull(struct Stack* stack) {
{ case '+':
if(stack->top == stack->maxSize - 1){ case '-':
printf("Will not be able to push maxSize reached\n"); return 1;
}
// Since array starts from 0, and maxSize starts from 1 case '*':
return stack->top == stack->maxSize - 1; case '/':
} return 2;

// By definition the Stack is empty when top is equal to -1 case '^':


// Will return true if top is -1 return 3;
int isEmpty(struct Stack* stack) }
{ return -1;
return stack->top == -1; }
}
// The driver function for infix to postfix conversion
// Push function here, inserts value in stack and increments int covertInfixToPostfix(char* expression)
stack top by 1 {
void push(struct Stack* stack, int item) int i, j;
{
if (isFull(stack)) // Stack size should be equal to expression size for safety
return; struct Stack* stack = create(strlen(expression));
stack->array[++stack->top] = item; if(!stack) // just checking is stack was created or not
} return -1 ;

// Function to remove an item from stack. It decreases top for (i = 0, j = -1; expression[i]; ++i)
by 1 {
int pop(struct Stack* stack) // Here we are checking is the character we scanned is
{ operand or not
if (isEmpty(stack)) // and this adding to to output.
return INT_MIN; if (checkIfOperand(expression[i]))
return stack->array[stack->top--]; expression[++j] = expression[i];
}
// Here, if we scan character ‘(‘, we need push it to the
// Function to return the top from stack without removing it stack.

64
else if (expression[i] == '(') #include<string>
push(stack, expression[i]); #define MAX 20
using namespace std;
// Here, if we scan character is an ‘)’, we need to pop
and print from the stack char stk[20];
// do this until an ‘(‘ is encountered in the stack. int top=-1;
else if (expression[i] == ')') // Push function here, inserts value in stack and increments
{ stack top by 1
while (!isEmpty(stack) && peek(stack) != '(') void push(char oper)
expression[++j] = pop(stack); {
if (!isEmpty(stack) && peek(stack) != '(') if(top==MAX-1)
return -1; // invalid expression {
else cout<<"stackfull!!!!";
pop(stack); }
}
else // if an operator else
{ {
while (!isEmpty(stack) && top++;
precedence(expression[i]) <= precedence(peek(stack))) stk[top]=oper;
expression[++j] = pop(stack); }
push(stack, expression[i]); }
} // Function to remove an item from stack. It decreases top
by 1
} char pop()
{
// Once all initial expression characters are traversed char ch;
// adding all left elements from stack to exp if(top==-1)
while (!isEmpty(stack)) {
expression[++j] = pop(stack); cout<<"stackempty!!!!";
}
expression[++j] = '\0'; else
printf( "%s", expression); {
} ch=stk[top];
stk[top]='\0';
int main() top--;
{ return(ch);
char expression[] = "((a+(b*c))-d)"; }
covertInfixToPostfix(expression); return 0;
return 0; }
} int priority ( char alpha )
{
if(alpha == '+' || alpha =='-')
Output
{
return(1);
abc*+d- }

if(alpha == '*' || alpha =='/')


{
Infix To Postfix Conversion using Stack in
return(2);
C++ }

// C++ Program infix to postfix expression using stack if(alpha == '$')


(array) in data structure {
#include<iostream> return(3);

65
} {
push(infix[i]);
return 0; i++;
} }
string convert(string infix)
{ else if( priority(infix[i]) <= priority(stk[top])) {
int i=0; postfix.insert(postfix.end(),pop());
string postfix = "";
while(infix[i]!='\0') while(priority(stk[top]) == priority(infix[i])){
{ postfix.insert(postfix.end(),pop());
if(infix[i]>='a' && infix[i]<='z'|| infix[i]>='A'&& if(top < 0) {
infix[i]<='Z') break;
{ }
postfix.insert(postfix.end(),infix[i]); }
i++; push(infix[i]);
} i++;
else if(infix[i]=='(' || infix[i]=='{' || infix[i]=='[') }
{ else if(priority(infix[i]) > priority(stk[top])) {
push(infix[i]); push(infix[i]);
i++; i++;
} }
else if(infix[i]==')' || infix[i]=='}' || infix[i]==']') }
{ }
if(infix[i]==')') while(top!=-1)
{ {
while(stk[top]!='(') postfix.insert(postfix.end(),pop());
{ postfix.insert(postfix.end(),pop()); }
} cout<<"The converted postfix string is : "<<postfix; //it
pop(); will print postfix conversion
i++; return postfix;
} }
if(infix[i]==']')
{ int main()
while(stk[top]!='[') {
{ int cont;
postfix.insert(postfix.end(),pop()); string infix, postfix;
} cout<<"\nEnter the infix expression : "; //enter the
pop(); expression
i++; cin>>infix;
} postfix = convert(infix);
return 0;
if(infix[i]=='}') }
{
while(stk[top]!='{') Output:-
{ Enter the infix expression : a=b*2+5
postfix.insert(postfix.end(),pop()); The converted postfix string is : ab*=+25
}
pop();
i++;
}
Infix to postfix in java
}
else import java.util.Stack;
{
if(top==-1)

66
public class InfixToPostfix { return false;

public static boolean isOperator(char op){ public static String convertInixToPostfix(String infix){

if(op == ‘+’ || op == ‘-‘ || op == ‘*’ || op == ‘/’ || op Stack<Character> stack = new Stack();


==‘%’)
StringBuilder sb = new StringBuilder();
return true;

return false;
for(int i=0; i<infix.length(); i++){
}
char currentCharacter = infix.charAt(i);

//If it’s an operand, put it on output string


/* precedence to an operator */
if(!isOperator(currentCharacter)){
public static int precedence(char op){
sb.append(currentCharacter);
switch (op){
}
case ‘+’ :
else{
case ‘-‘ :
if(stack.empty()) stack.push(currentCharacter);
return 1;
else{
case ‘/’ :
while(!stack.empty()
case ‘*’ :
&& isLowerPrecedence(currentCharacter,
return 2; stack.peek())){

case ‘%’ : sb.append(stack.pop());

return 3; }

default : stack.push(currentCharacter);

return 4; }

} }

} }

while(!stack.empty()) sb.append(stack.pop());

/* This function tell if the op1 has lower precedence than


op2 */
return sb.toString();
public static boolean isLowerPrecedence(char op1, char
op2){ }

if(precedence (op1) < precedence(op2))

return true; public static void main(String[] args){

67
System.out.println(convertInixToPostfix(“4*5+6/7”)); Example – ((a / b) + c) - (d + (e * f ))

}
2. Prefix: Expressions wherein the operator comes before
}
the operands are prefix expression like – Infix: (A + B) can
OUTPUT: be expressed as +AB

Example – Prefix result would be : -+/abc+d*ef


input:

3. Postfix: Expression operator comes after the operands

3+6*4/8 are prefix expression like – Infix: (A + B) can be expressed

as AB+

output: Example – Prefix result would be: ab/c+def*+-

Steps to convert
36*48/+

● Any infix op1 oper op2 can be written as op1 op2


ADVANTAGE OF POSTFIX:
oper
Any formula can be expressed without parenthesis.
○ Where op1 = Operand 1
It is very convenient for evaluating formulas on a computer
with stacks. ○ op2 = Operand2

○ oper = Operation
Postfix expression doesn’t have the operator precedence.
● Example a + b can be written as ab+ in prefix
Postfix is slightly easier to evaluate.

It reflects the order in which operations are performed.

You need to worry about the left and right associativity. Problem (This is how to convert manually for MCQ
Question in the exam)

Infix to prefix expression using stacks:


● Infix: (a / b + c) - ( d + e * f) can be written as ((a
As we know for the compiler it may be difficult to read an / b) + c) - ( d + (e * f))
infix expression as it can’t start operations and assignments
until it has read the whole expression and know about ● Now, we have done the above according to
precedence of various operations in the expression.
associativity

While prefix expression is easier for the compiler, as it is ● Solving and converting innermost bracket to
already sorted in accordance with precedence and compiler,
can start assignments and operations, without caring about prefix
precedence. ● Step 1 –(/ab + c) - ( d + *ef)
What are infix and prefix expressions?
● Step 2 – Consider /ab and *ef as separate operand
1. Infix: Expressions of format (A + B) are called as infix
x and y
expressions, these are just like mathematical expressions

68
● the innermost bracket now looks like (x + c) - (d // we are storing string in integer array, this will not give
error
+ y)

○ Applying prefix it looks like – (+xc - // as values will be stored in ASCII and returned in ASCII
thus, returned as string again
+dy)replacing x and y here (+/abc -
int* array;
+d*ef)

● Step 3 – Considering/abc and+d*efas separate };

operand z and w, the final bracket looks like – (z


struct Stack* create(int max)
- w)the result would be -zw
{
○ replacing z and w value = -+/abc+d*ef
struct Stack* stack = (struct Stack*)malloc(sizeof(struct
Stack));

stack->maxSize = max;

stack->top = -1;

stack->array = (int*)malloc(stack->maxSize *
sizeof(int));

return stack;

// Checking with this function is stack is full or not

// Will return true is stack is full else false

C Code for Infix to Prefix Conversion //Stack is full when top is equal to the last index

#include <limits.h> int isFull(struct Stack* stack)

#include <stdio.h> {

#include <stdlib.h> if(stack->top == stack->maxSize - 1){

#include <string.h> printf("Will not be able to push maxSize reached\n");

// A structure to represent a stack // Since array starts from 0, and maxSize starts from 1

struct Stack { return stack->top == stack->maxSize - 1;

int top; }

int maxSize; // By definition the Stack is empty when top is equal to -1

69
// Will return true if top is -1 return stack->array[stack->top];

int isEmpty(struct Stack* stack) }

return stack->top == -1; // A utility function to check if the given character is


operand
}
int checkIfOperand(char ch)

{
// Push function here, inserts value in stack and increments
stack top by 1 return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');

void push(struct Stack* stack, int item) }

{ // Fucntion to compare precedence

if (isFull(stack)) // If we return larger value means higher precedence

return; int precedence(char ch)

stack->array[++stack->top] = item; {

} switch (ch)

// Function to remove an item from stack. It decreases top {


by 1
case '+':
int pop(struct Stack* stack)
case '-':
{
return 1;
if (isEmpty(stack))

return INT_MIN;
case '*':
return stack->array[stack->top--];
case '/':
}
return 2;
// Function to return the top from stack without removing it

int peek(struct Stack* stack)


case '^':
{
return 3;
if (isEmpty(stack))
}
return INT_MIN;

70
return -1; {

} while (!isEmpty(stack) && peek(stack) != '(')

expression[++j] = pop(stack);

// The driver function for infix to postfix conversion if (!isEmpty(stack) && peek(stack) != '(')

int getPostfix(char* expression) return -1; // invalid expression

{ else

int i, j; pop(stack);

// Stack size should be equal to expression size for safety }

struct Stack* stack = create(strlen(expression)); else // if an opertor

if(!stack) // just checking is stack was created or not {

return -1 ; while (!isEmpty(stack) &&


precedence(expression[i]) <= precedence(peek(stack)))
for (i = 0, j = -1; expression[i]; ++i)
expression[++j] = pop(stack);
{
push(stack, expression[i]);
// Here we are checking is the character we scanned is
operand or not }

// and this adding to to output. }

if (checkIfOperand(expression[i])) // Once all inital expression characters are traversed

expression[++j] = expression[i]; // adding all left elements from stack to exp

// Here, if we scan character ‘(‘, we need push it to the while (!isEmpty(stack))


stack.
expression[++j] = pop(stack);
else if (expression[i] == '(')

push(stack, expression[i]);
expression[++j] = '\0';

// Here, if we scan character is an ‘)’, we need to pop


and print from the stack
}

// do this until an ‘(‘ is encountered in the stack.

else if (expression[i] == ')')


void reverse(char *exp){

71
int size = strlen(exp); int size = strlen(exp);

int j = size, i=0;

char temp[size]; // reverse string

reverse(exp);

temp[j--]='\0'; //change brackets

while(exp[i]!='\0') brackets(exp);

{ //get postfix

temp[j] = exp[i]; getPostfix(exp);

j--; // reverse string again

i++; reverse(exp);

} }

strcpy(exp,temp);

} int main()

void brackets(char* exp){ {

int i = 0; printf("The infix is: ");

while(exp[i]!='\0')

{ char expression[] = "((a/b)+c)-(d+(e*f))";

if(exp[i]=='(') printf("%s\n",expression);

exp[i]=')'; InfixtoPrefix(expression);

else if(exp[i]==')')

exp[i]='('; printf("The prefix is: ");

i++; printf("%s\n",expression);

} return 0;

void InfixtoPrefix(char *exp){ }

72
Output – stack->top = -1;
stack->array = (int *) malloc (stack->maxSize * sizeof
(int));
The Infix is: ((a/b)+c)-(d+(e*f)) return stack;
}
The prefix is: -+/abc+d*ef
// Checking with this function is stack is full or not
int stackFull (struct Stack *stack)
C++ Program for Infix To Prefix Conversion {
using stack data structures:- if (stack->top == stack->maxSize - 1)
{
#include <iostream> cout << "Will not be able to push maxSize reached\n";
#include <limits.h> }
#include <stdio.h> // We know array index from 0 and maxSize starts from 1
#include <stdlib.h> return stack->top == stack->maxSize - 1;
#include <string.h> }
using namespace std;
//definition of functions // if Stack is empty when top is equal to -1 and return true
struct Stack *create (int max); int stackEmpty (struct Stack *stack)
int stackFull (struct Stack *stack); {
int stackEmpty (struct Stack *stack); return stack->top == -1;
void pushElement (struct Stack *stack, int item); }
int popElement (struct Stack *stack);
int peekElement (struct Stack *stack); // Push function it inserts value in stack and increments
int checkOperand (char ch); stack top by 1
int precedence (char ch); void pushElement (struct Stack *stack, int item)
int postfix (char *expression); {
void reverse (char *exp); if (stackFull (stack))
void brackets (char *exp); return;
void conversionInfixToPrefix (char *exp); stack->array[++stack->top] = item;
// A structure to represent a stack }
struct Stack
{ // pop Function it remove an item from stack and decreases
int top; top by 1
int maxSize; int popElement (struct Stack *stack)
int *array; {
}; if (stackEmpty (stack))
int main () return INT_MIN;
{ return stack->array[stack->top--];
int n = 10; }
cout << "The infix expression is: \n";
char expression[] = "(P+(Q*R)/(S-T))"; // Function to return the top from stack without removing it
cout << expression << "\n"; int peekElement (struct Stack *stack)
conversionInfixToPrefix (expression); {
cout << "The prefix expression is: \n"; if (stackEmpty (stack))
cout << expression; return INT_MIN;
return 0; return stack->array[stack->top];
} }
//stack implementation
struct Stack * create (int max) // A function check the given character is operand
{ int checkOperand (char ch)
struct Stack *stack = (struct Stack *) malloc (sizeof (struct {
Stack)); return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
stack->maxSize = max; }

73
{
// Fucntion to compare precedence if return larger value while (!stackEmpty (stack)
means higher precedence && precedence (expression[i]) <=
int precedence (char ch) precedence (peekElement (stack)))
{ expression[++j] = popElement (stack);
switch (ch) pushElement (stack, expression[i]);
{ }
case '+':
case '-': }
return 1;
// if all first expression characters are scanned
case '*': // adding all left elements from stack to expression
case '/': while (!stackEmpty (stack))
return 2; expression[++j] = popElement (stack);
expression[++j] = '\0';
case '^': }
return 3;
} void reverse (char *exp)
return -1; { //reverse function
} for expression

// The function for infix to postfix conversion int size = strlen (exp);
int postfix (char *expression) int j = size, i = 0;
{ char temp[size];
int i, j;
struct Stack *stack = create (strlen (expression)); temp[j--] = '\0';
if (!stack) while (exp[i] != '\0')
return -1; {
temp[j] = exp[i];
for (i = 0, j = -1; expression[i]; ++i) j--;
{ i++;
// checking the character we scanned is operand or not }
if (checkOperand (expression[i])) strcpy (exp, temp);
expression[++j] = expression[i]; }

// if we scan character push it to the stack void brackets (char *exp)


else if (expression[i] == '(') {
pushElement (stack, expression[i]); int i = 0;
while (exp[i] != '\0')
//if we scan character we need to pop and print from the {
stack if (exp[i] == '(')
else if (expression[i] == ')') exp[i] = ')';
{ else if (exp[i] == ')')
while (!stackEmpty (stack) && peekElement exp[i] = '(';
(stack) != '(') i++;
expression[++j] = popElement (stack); }
if (!stackEmpty (stack) && peekElement (stack) }
!= '(')
return -1; // invalid void conversionInfixToPrefix (char *exp)
expression {
else int size = strlen (exp);
popElement (stack); reverse (exp);
} brackets (exp);
else // if an operator postfix (exp);

74
reverse (exp); stack.push(c);
} }else if(c==‘)’){
Output:- char x = stack.pop();
The infix expression is: while(x!=‘(‘){
(P+(Q*R)/(S-T)) result.append(x);
The prefix expression is: x = stack.pop();
+P/*QR-ST }
}else if(c==‘(‘){
stack.push(c);
}else{
Java code : //character is neither operator nor “(“
import java.util.Stack; result.append(c);
public class InfixToPreFix { }
static int precedence(char c){ }
switch (c){
case ‘+’: for (int i = 0; i <=stack.size() ; i++) {
case ‘-‘: result.append(stack.pop());
return 1; }
case ‘*’: return result.reverse();
case ‘/’: }
return 2;
case ‘^’: public static void main(String[] args) {
return 3; String exp = “A+B*(C^D-E)”;
} System.out.println(“Infix Expression: “ + exp);
return –1; System.out.println(“Prefix Expression: “ +
} infixToPreFix(exp));
}
static StringBuilder infixToPreFix(String expression){ }
Output:
StringBuilder result = new StringBuilder();
StringBuilder input = new StringBuilder(expression); Infix Expression: A+B*(C^D-E)
input.reverse(); Prefix Expression: +A*B-^CDE
Stack<Character> stack = new Stack<Character>();

char [] charsExp = new String(input).toCharArray();


for (int i = 0; i < charsExp.length; i++) {
Postfix to prefix conversion using stack
As we already know that any given operation in a compiler
if (charsExp[i] == ‘(‘) { can be expressed in 3 ways which are Infix, postfix and
charsExp[i] = ‘)’; prefix, we shall see how to convert postfix to prefix
i++; operation via manual calculation and via code.
}
else if (charsExp[i] == ‘)’) { What postfix, infix, prefix rules are –
charsExp[i] = ‘(‘;
i++;
}
} ● Infix: (X + Y)
for (int i = 0; i <charsExp.length ; i++) {
char c = charsExp[i]; ● Postfix – The postfix will look like, XY+

● Prefix: The prefix will look like, +YX


if(precedence(c)>0){
while(stack.isEmpty()==false &&
precedence(stack.peek())>=precedence(c)){
result.append(stack.pop()); Infix : (X + Y) / (U – V)
}

75
● Postfix – The postfix will look like, XY+UV-/

● Prefix – The prefix will look like, /+XY-UV

If we want to get postfix to infix all of us generally convert

postfix to the infix and then convert Infix to prefix, as this

is easier to do, and we even recommend doing the same.

*What when Postfix is given and you want to calculate

Prefix directly?

*Or if you want to code the same, doing temporary

conversion to Infix will be time-consuming and longer code

will be there.

Following is the algorithm-

A + B, where A and B are operands and + is operator, the

whole A + B is expression.

1.Start reading the expression from L – R i.e. Left to right

If you encounter an operand, then do push in the stack

1. If we encounter an operator then, pop two operands from

the stack, and concatenate them, in +AB type of format

2. And push the resultant sting back to the stack

3. Repeat the above steps till end of the expression

Code for Postfix to Prefix in C

● Postfix: abc*d/+ed*- However, to code, we will apply different logic as it is


● Prefix: -+a/*bcd*ed difficult to push into the stack when we have a 2D array in
● Infix: ((a+((b*c)/d))-(e*d)) C. For example, pushing a character ‘a’ is fine but pushing

*bc which is a string and in a stack which already is an

Below is an implementation for it array needs a 2D array, so we use other implementations in

C. Please follow the code below and you will understand

how this implementation works.

76
Note – It has a different logic than the above rule {

explained.
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');

}
C code to conversion of postfix to prefix

//function to check if it is an operator


#include<stdio.h>
int isOperator(char x)
#include<conio.h>
{
#include<string.h>
switch (x) {
#include<stdlib.h>
case '+':

case '-':
#define MAX 20
case '/':

case '*':
char str[MAX], stack[MAX];
return 1;
int top = -1;
}

return 0;
void push(char c)
}
{

stack[++top] = c;
void postfixToprfix()
}
{

int n, i, j = 0;
char pop()
char c[20];
{
char a, b, op;
return stack[top--];

}
printf("Enter the postfix expression\n");
// A utility function to check if the given character is
operand scanf("%s", str);

int checkIfOperand(char ch)

77
n = strlen(str); char d[20];

for (i = 0; i < MAX; i++) while (c[i] != '\0') {

stack[i] = '\0'; d[j--] = c[i++];

printf("Prefix expression is:\t"); }

for (i = n - 1; i >= 0; i--) printf("%s\n", d);

if (isOperator(str[i])) }

{ int main()

push(str[i]); {

} else postfixToprfix();

c[j++] = str[i]; return 0;

while ((top != -1) && (stack[top] == '#')) }

a = pop(); import java.util.Stack;

c[j++] = pop(); public class PostFixToPreFix {

push('#'); static boolean isOperator(char x){

} switch (x){

} case ‘-‘:

c[j] = '\0'; case ‘+’:

case ‘/’:

i = 0; case ‘*’:

j = strlen(c) - 1; case ‘^’:

78
return true; String postfix = “AB+CD-*”;

} System.out.println(“Postfix exp: “ + postfix);

return false; System.out.println(“Prefix exp: “ + convert(postfix));

} }

Java code for conversion of postfix to prefix }

public static String convert(String exp){ output:

Stack<String> st = new Stack<>(); postfix exp:

for (int i = 0; i exp.length() ; i++) {

AB+CD-*

char c = exp.charAt(i);

prefix exp:

if(isOperator(c)){

String s1 = st.pop(); *+AB-CD

String s2 = st.pop();

String temp = c + s2 + s1;

st.push(temp);

}else{

st.push(c+“”);

String result = st.pop();

return result;

public static void main(String[] args) {

79
Why do we use Linked List in Data
Structure?
Generally, storage arrays are used. But, there are many
many disadvantaged with arrays –

Fixed Size
The size of the array is fixed and needs to be pre-defined
Example – int a[10]; or int a[ ] = {1, 2, 3, 4, 5}
We can’t declare an array without declaring the size.
Memory wastage (Not Optimised)
If you declare an array of size 10 and just assign values to
first two elements
The memory is allocated to all of them even though we
may not end up using them.
Need for Contiguous Memory
Arrays need Contiguous memory, which sometimes is bad.

Chapter 13. Linked List Example – Consider there are only three memories of size
10, 10 and 400
We need to store an array of size 15
What is a Linked List in Data Structure?
In this case, the array will use memory location size 400
A linked list is a linear data structure. In which we can
and not combine memory A and B of size 10 and 10
store the data in a sequence manner. Unlike an array linked
respectively.
list is dynamic data structure the size of a linked list can
Thus wasting a lot of memory
grow or shrink depending on the situation.

The element of a linked list is called a node. Every element Inserting in Array is expensive
or node contains two main entities. The first entity is the Let us say you have an array a[] = {10, 20, 40, 60, 80} and
information or the data whereas the second entity is the we need to add 50 in the same sorted format.
pointer to the next node. Then, we have to move all elements after 40 to one
additional position
More Information Also, same goes for deletion if we want to delete 20. Then
The structure of the linked list is like a train. A linked list all elements after it have to be moved to one position in the
has the following components – opposite direction.

Data: Data is the value stored in it, it could be anything, an Linked Lists Advantages
integer or a string or anything else really. Ease of insertion and deletion. (How? we will learn this in
Pointer (Link) – Each linked list contains a pointer which Linked List insertion Post)
points to the address of the next node in the linked list train. Dynamic Size
Apart from this the following are also keywords used in
linked lists – Disadvantages
We have to search elements linearly, and can’t do random
Node – Any single unit of a linked list, its data and access
pointer(s), is called a node. We can’t do efficient searches like binary search
Head: First is the head who is defined at the beginning of Extra space for pointers is needed
the list. Linked lists are not cache friendly as arrays are stored in
Tail: second is tail which defines the end of the list. contiguous format they can be cached easily
Loss of data threat is there, if we lose one pointer location
What is a linked list the rest of the linked list can’t be accessed.
Linked List like an array is a linear data structure.
However, the elements or data storage of linked list
elements are not in a contiguous manner and we use
Types of Linked link
pointers to create linearity in linked lists. There are three types of linked list, that are mentioned in
following ways-

80
Singly linked list }
Doubly linked list }
Circular linked list
Python Code:
# Node class
class Node:

# Function to initialize the node object


def __init__(self, data):
self.data = data # Assign data
self.next = None # Initialize
# next as null

# Linked List class


class LinkedList:
Singly-linked list
In a singly list there are the two fields on the list.
# Function to initialize the Linked
# List object
Data: First field is data that it stores
def __init__(self):
Link (pointer): Link that refers to the address of the next
self.head = None
linked list node.
The last node of linked list points to NULL and means end
of the list Program to Create a Singly List
In a Singly linked list node, it only contains the address of Here we will construct a linked list with 4 elements as
the next node and not the previous node, so we can only follows –
traverse in one direction only.

C Code:
struct Node {
int data; C Code:
struct Node* next; //We are creating program for linked list creation
}; #include <stdio.h>
#include <stdlib.h>
C++ Code: //stdlib used to provide a declaration of ‘malloc’
class Node {
public: // structure of linked list
int data; struct Node {
Node* next; int data;
}; struct Node* next;
// Pointer pointing towards next node
Java COde: };
class LinkedList {
Node head; // head //function to print the linked list
void display(struct Node* node)
/* Linked list Node*/ {
class Node { while (node != NULL) {
int data; printf(" %d ", node->data);
Node next; node = node->next;
}
// For creating new node a Constructor }
// Next is by default initialized
// as null // main function
Node(int d) { data = d; } int main()

81
{ */
//creating 4 pointers of type struct Node
//So these can point to address of struct type variable display(head);
struct Node* head = NULL;
struct Node* node2 = NULL; return 0;
struct Node* node3 = NULL; }
struct Node* node4 = NULL;

// allocate 3 nodes in the heap


head = (struct Node*)malloc(sizeof(struct Node));
node2 = (struct Node*)malloc(sizeof(struct Node));
node3 = (struct Node*)malloc(sizeof(struct Node));
node4 = (struct Node*)malloc(sizeof(struct Node));

/* Using malloc method we have created 4 memory


blocks
Each memory block is of type struct and has int data and
Pointer of type Node
So it can point towards a node type struct.
Doubly linked list
head node2 node3 node4 A doubly linked list is a kind of complex linked list, in
| | | | which it contains the address of the previous node as well
| | | | as the next node. A doubly linked list contains the
+---+-----+ +----+----+ +----+----+ +----+----+ following –
|data|next| |data|next| |data|next| |data|next|
+---+-----+ +----+----+ +----+----+ +----+----+ 1. Data: The data present in the node.
2. Link (Previous) – A pointer to the previous node in
# As of now data has garbage value and its pointer the linked list.
points towards random addresses*/ 3. Link (Next) – A pointer to the next node in the linked
list
head->data = 5; // data set for head node In this way, for a doubly-linked list we can travel in
head->next = node2; // next pointer assigned to address of both directions for traversals.
node2

node2->data = 10;
node2->next = node3; Introduction to Doubly Linked
node3->data = 12;
List
node3->next = node4;
What are Doubly Linked Lists?
Doubly linked lists are an extension to singly linked lists
node4->data = 3;
and provide a little more additional features and security to
node4->next = NULL;
singly-linked lists. Let us see what these linked lists are –
//last node assigned to Null as linked list ends here

/* Finally linked list looks like

head node2 node3 node4


| | | |
| | | |
+---+-----+ +----+----+ +----+----+ +----+----+
| 5 | next|---->| 10 | next|--->|12 | next|---->| 3 | next| --->
NULL
+---+-----+ +----+----+ +----+----+ +----+----+

82
C Code:
struct Node {
int Data;
Struct Node* next;
Struct Node* prev;
};

Code for Insertion and Access for Linked list


Doubly Linked list //We are creating program for doubly linked list creation
Doubly linked lists have the following – #include <stdio.h>
#include <stdlib.h>
Data: Like Singly-linked lists, it also contains data that is //stdlib used to provide a declaration of ‘malloc’
stored.
Pointer (next) – Contains the address of the next node in // structure of linked list
the doubly linked list struct Node {
Pointer (previous) – Contains the address of the previous int data;
node in the doubly linked list struct Node* next;
Apart from these basic terminologies are same – Node, struct Node* prev;
Head, Tail // Pointer pointing towards next node
};
Doubly linked list
Advantages //function to print the doubly linked list
1. It is better as unlike singly linked list, in a doubly-linked void display(struct Node* node)
list we can traverse in both directions. Thus, if in case any {
pointer is lost we can still traverse. struct Node *end;
Thus, in a Doubly Linked List we can traverse from Head printf("List in Forward direction: ");
to Tail as well as Tail to Head. while (node != NULL) {
2. Delete operation is quicker if the pointer to the node to printf(" %d ", node->data);
be deleted is given to us already. end = node;
3. Insertion is quicker in doubly-linked lists. node = node->next;
}
Disadvantages
1. Extra space is required for the previous pointer for printf("\nList in backward direction: ");
doubly-linked lists(DLL)
2. All operations require an additional modification of the while (end != NULL) {
previous pointer as well along with the next pointer. printf(" %d ", end->data);
end = end->prev;
Creation of Doubly linked lists }
Now we are discussing How to create a Node for a Doubly
linked list.
}

83
// main function head node2 node3 node4
int main() | | | |
{ | | | |
//creating 4 pointers of type struct Node +---++---+-----+ +----+----+----+ +----+----+----+
//So these can point to address of struct type variable +----+----+----+
struct Node* head = NULL; |prev| 5 |next|--->|prev| 10 |next|--->|prev| 12
struct Node* node2 = NULL; |next|--->|prev| 3 |next|
struct Node* node3 = NULL; +---++---+-----+ +----+----+----+ +----+----+----+
struct Node* node4 = NULL; +----+----+----+

// allocate 4 nodes in the heap */


head = (struct Node*)malloc(sizeof(struct Node));
node2 = (struct Node*)malloc(sizeof(struct Node));
node3 = (struct Node*)malloc(sizeof(struct Node)); display(head);
node4 = (struct Node*)malloc(sizeof(struct Node));
return 0;
/* Using malloc method we have created 4 memory }
blocks
Each memory block is of type struct and has int data and
Pointer of type Node
Circular linked list
So it can point towards a node type struct.
This is a type of linked list in which the last node points to
head node2 node3 node4 the starting node. There is no null at the end. A circular
| | | | linked list can be a singly circular linked list and doubly
| | | | circular linked list. In the Circular linked list there exist no
+---++---+-----+ +----+----+----+ +----+----+----+ nodes which have null at address space.
+----+----+----+
|prev|data|next| |prev|data|next| |prev|data|next|
|prev|data|next| Introduction to Circular linked list
+---++---+-----+ +----+----+----+ +----+----+----+
Circular Linked Lists - Circular linked lists are just like
+----+----+----+
singly linked lists but all of its nodes are connected to form
a circle
# As of now data has garbage value and its pointer
points towards random addresses*/

head->data = 5; // data set for head node


head->next = node2; // next pointer assigned to address of
node2
head->prev = NULL;

node2->data = 10;
node2->next = node3;
node2->prev = head;

node3->data = 12;
node3->next = node4;
node3->prev = node2;

node4->data = 3;
node4->next = NULL;
node4->prev = node3;
Circular linked list Advantages
//last node assigned to Null as linked list ends here
The circular linked list is also two types.
/*

84
1. Singly linked list struct node *prev;
2. Doubly linked list };

In a singly circular linked list, the address of the last node’s


next pointer rather than being NULL is pointed towards the
address of the head node.

Similarly, in a doubly linked list, in addition to the address


of the last node’s next pointer being the address of head
node. The previous pointer of the head node is provided to
the address of the last node.

Advantages
1. Any node can be starting point and we can still traverse
the whole list Function to traverse in a Circular linked list
2. It can also deem to be useful for implementation as
queues as rather than maintaining the Front and Rear, we
can use a circular linked list and just maintain the pointer to void display(struct Node *head)
the first inserted node and it can simply be the next node to
the last node. {
3. Circular linked lists are commonly used in OS’es for the
task that requires repeatedly to be executed by OS.
struct Node *temp = head;

Disadvantages
if (head != NULL)
1. Doubly Linked List is faster in getting previous node
information due to previous pointer.
2. Doubly Linked List can traverse in both forward and {
backward direction.
3. Finding end of list and loop control is harder (no NULL do
to mark beginning and end).
4. The entire list can be traversed starting from any node {
(traverse means visit every node just once).
So, when we want to traverse the node in a circular linked
printf("%d ", temp->data);
list so we will traverse in a singly circular linked list so, it
is just like the singly linked list where tail nodes hold the
address of head node so traversal can be done circularly in temp = temp->next;
only one direction.
}
And the Traversal in a doubly linked list can be done
circularly in both directions.
while (temp != head);

Creation of Circular Linked Lists


}
Creation of the list node is same as singly or doubly only
implementation with the struct is different
}
Defining struct for Circular Linked List (Singly)
struct node{
int data; Code of Circular linked list
struct node *next;
}; //We are creating program for linked list creation
Defining struct for Circular Linked List (Doubly) #include <stdio.h>
struct node{ #include <stdlib.h>
int data; //stdlib used to provide a declaration of ‘malloc’
struct node *next;

85
// structure of Circular linked list head->data = 5; // data set for head node
struct Node { head->next = node2; // next pointer assigned to address of
int data; node2
struct Node* next;
// Pointer pointing towards next node node2->data = 10;
}; node2->next = node3;

//function to print the Circular linked list node3->data = 12;


void display(struct Node *head) node3->next = node4;
{
struct Node *temp = head; node4->data = 3;
if (head != NULL) node4->next = head;
{ //last node assigned to head node as linked list ends here
do //this completes Circular linked list
{
printf("%d ", temp->data); /* Finally Circular linked list looks like
temp = temp->next;
} head node2 node3 node4
while (temp != head); | | | |
} | | | |
} +---+-----+ +----+----+ +----+----+ +----+----+
| 5 | next|---->| 10 | next|--->|12 | next|---->| 3 | next| ---> |
// main function +---+-----+ +----+----+ +----+----+ +----+----+ |
int main() ^ |
{ | |
//creating 4 pointers of type struct Node -------------------------------------------------------------
//So these can point to address of struct type variable */
struct Node* head = NULL;
struct Node* node2 = NULL; display(head);
struct Node* node3 = NULL;
struct Node* node4 = NULL; return 0;
}
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
node2 = (struct Node*)malloc(sizeof(struct Node));
node3 = (struct Node*)malloc(sizeof(struct Node));
node4 = (struct Node*)malloc(sizeof(struct Node));

/* Using malloc method we have created 4 memory


blocks
Each memory block is of type struct and has int data and
Pointer of type Node
So it can point towards a node type struct.

head node2 node3 node4


| | | |
| | | |
+---+-----+ +----+----+ +----+----+ +----+----+
|data|next| |data|next| |data|next| |data|next|
+---+-----+ +----+----+ +----+----+ +----+----+

# As of now data has garbage value and its pointer


points towards random addresses*/

86
Linked List does not need contiguous memory, i.e; if one
Chapter 14- Linked List in node has an address of 1000 then the next node may have
the address 2000.
C Insertion and Deletion Operation in Linked Lists are pretty
easy and less complicated.
Disadvantages of using Linked List in C
Linked Lists in C Programming Language Although insertion and deletion are not a difficult task in
Linked List in C is a linear type of data structures, which Linked List, searching in Linked List is very difficult.
has some major advantages over arrays and other linear We cannot use efficient searches like Binary Search.
data structures. Linked Lists in C are used for storing the It takes more spaces, as it stores the address also.
data in a contiguous manner. It is not necessary on the Linked lists are not cache friendly as arrays are stored in
concept of linked lists that the address to the next node is contigious format they can be cached easily
provided in continuous manner.Linked is constructed of Loss of data threat is there, if we lose one pointer location
two parts-: the rest of linked list can’t be accessed.

Node – It contains the data


Pointer – It contains the address of the next node

Why do we prefer Linked Lists ?


Linked Lists are a more preferable data structure to use
than any other data structure if we are willing to store large
amount of data, as insertion and deletion process in linked
lists are fairly easy and less complicated in comparison
with other data structures.

Linked List
Linked List is like an array is a linear data structure.
However, the elements or data storage of linked list Code for Implementing Linked List in C
elements are not in a contiguous manner and we use
pointers to create linearity in linked lists.×Dismiss alert //Linked List Implementation code
How to construct a Linked List in C ? #include <stdio.h>
For constructing a Linked List in C we use user defined #include <stdlib.h>
data type, i.e. we make a structure in C for using Linked //stdlib is included because we will be using ‘malloc’
List. We design a user defined struct data type, that
contains a datatype, for storing the desired data and a // creating a node in linked list
pointer variable for storing the address of the next node in struct Node {
the Linked List. int data;
struct Node* next;
Syntax for creating a node in Linked List in C // Pointer pointing towards next node
struct Node { };
int data;
struct Node* next; //function to print the linked list
}; void display(struct Node* node)
This code will create a new node in a Linked List which {
will be storing integer type of data while (node != NULL) {
printf(" %d ", node->data);
Advantages of using Linked List in C node = node->next;
It does not have a restriction of size, i.e; we do not have to }
declare the size of linked list before creating it. }
There is no memory wastage, as we connect new nodes
depending upon how much data do we have to store, and on // main function
deleting a data its node is also deleted. int main()
{
//creating 4 pointers of type struct Node

87
//So these can point to address of struct type variable June 17, 2020
struct Node* head = NULL;
struct Node* node2 = NULL; Insertion at begin in Singly linked list in C++ programming
struct Node* node3 = NULL; How to perform insertion at beginning in Singly Linked
struct Node* node4 = NULL; List in C++?
Insertion at Beginning in Singly Linked List in C++, is one
// allocate 3 nodes in the heap of the operations that we can perform on Linked List.
head = (struct Node*)malloc(sizeof(struct Node)); Singly linked list in C++ are part of linked list and is a type
node2 = (struct Node*)malloc(sizeof(struct Node)); of linear data structure. Linked is made up of two parts
node3 = (struct Node*)malloc(sizeof(struct Node)); node and pointer where node contains the data and pointer
node4 = (struct Node*)malloc(sizeof(struct Node)); contains the address of the next node.

To add a new node add beginning we need to allocate space


head->data = 10; // data set for head node for the new node first, then we have to store the address of
head->next = node2; // next pointer assigned to address previous head in the pointed of newly created node and
of node2 make the new node as head of the linked list. In this way
insertion at beginning is done in linked list.
node2->data = 20;
node2->next = node3; Singly linked list definition in C++
Nodes of singly linked list is created by using the code
node3->data = 30; mentioned besides.
node3->next = node4; This set of code will construct linked list by creating each
node of the list.
node4->data = 40;
node4->next = NULL; class Node
{
int data;
display(head); Node *next;
};
return 0; Steps to insert an element at beginning of singly linked list
} 1.) Allocate space for a new node.

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


Output 2.) In the space created for new node put the data in.

10 20 30 40 new_node->data = new_data
3.) Point the pointer of new node to the head of singly
linked list

Insertion operations on linked list new_node->ptr = (*head);


Insertion at beginning 4.) Make new node as head.
Insertion at end
Insertion in between of nodes. (*head) = new_node
Deletion operations on linked list Singly Linked List
Deletion at beginning We can traverse in only one direction in singly linked list as
Deletion at end singly linked list does not contain previous pointer, it only
Deletion of a specific node. has next pointer.×Dismiss alert
Other operations on linked list Insertin at beginning in singly linked list in C++
Reverse a linked list Algorithm to insert an element at beginning of singly
Search an element in linked list linked list
Find middle of the linked list IF PTR = NULL
Fold a linked list EXIT
ELSE SET NEW_NODE = PTR
Insertion at Beginning in Singly Linked List in C++ SET PTR = PTR → NEXT

88
SET NEW_NODE → DATA = VALUE stnode-> nextptr = NULL; //Links the address field to
SET NEW_NODE → NEXT = HEAD NULL
SET HEAD = NEW_NODE tmp = stnode;
EXIT
C++ program to insert an element at beginning of singly for(i=2; i<=n; i++)
linked list {
#include <iostream> frntNode = (struct node *)malloc(sizeof(struct
using namespace std; node));

struct node
{ if(frntNode == NULL) //If frntnode is null no
int num; memory cannot be alloted
node *nextptr; {
}*stnode; //node constructed cout<<" Memory can not be allocated";
break;
void createList(int n); }
void insertatBegin(int num); else
void display(); {
cout<<"Enter the data for node "<<i<<": "; //
int main() Entering data in nodes.
{ cin>>num;
int n,num; frntNode->num = num;
frntNode->nextptr = NULL;
cout<<"Enter the number of nodes: "; tmp->nextptr = frntNode;
cin>>n; tmp = tmp->nextptr;
createList(n); }
cout<<"\nLinked list data: \n"; }
display(); }
cout<<"\nEnter data you want to insert at the beginning: }
";
cin>>num; void insertatBegin(int num) //function to insert element at
insertatBegin(num); beginning
cout<<"\nLinked list after insertion: \n"; {
display(); struct node *frntNode;
frntNode = (struct node*)malloc(sizeof(struct node));
return 0; if(frntNode == NULL)
} {
void createList(int n) //function to create linked list. cout<<" Memory can not be allocated";
{ }
struct node *frntNode, *tmp; else
int num, i; {
frntNode->num = num; //Linkinking data
stnode = (struct node *)malloc(sizeof(struct node)); frntNode->nextptr = stnode; //Linking address
if(stnode == NULL) stnode = frntNode;
{ }
cout<<" Memory can not be allocated"; }
}
else void display() //function to print linked list
{ {
struct node *tmp;
cout<<"Enter the data for node 1: "; if(stnode == NULL)
cin>>num; {
stnode-> num = num; cout<<" No data found in the list";
}

89
else Node *next;
{ };
tmp = stnode; Steps to insert an element at end of singly linked list
cout<<"Linked List: "; 1.) Allocate space for a new node.
while(tmp != NULL)
{ new_node = (struct node *) malloc(sizeof(struct node *));
cout<<"\t"<<tmp->num; 2.) In the space created for new node put the data in.
tmp = tmp->nextptr;
} new_node->data = new_data
} 3.) Point the pointer of new node to null
}
Output: new_node->ptr = NULL;
Enter the number of nodes: 4 4.) If the Linked List is empty, then make the new node as
Enter the data for node 1: 11 head
Enter the data for node 2: 22
Enter the data for node 3: 33 if (*head == NULL)
Enter the data for node 4: 44 *head = new_node;
5.) Traverse till last node and point the pointer of this node
Linked list data: to new node.
Linked List: 11 22 33 44
Enter data you want to insert at the beginning: 55 while (last->next != NULL)
last = last->next;
Linked list after insertion: last->ptr = new_node;
Linked List: 55 11 22 33
44
Did you know!
We can traverse in only one direction in singly linked list as
Insertion at End in Singly Linked List in C++ singly linked list does not contain previous pointer, it only
has next pointer.×Dismiss alert

Algorithm for insertion at end in singly linked list in C++ Algorithm for Insertion at end in singly linked list in
How to insert element at End in Singly Linked List in C++? c++
To add a new node at end we need to allocate space for the
new node first, then we have to store null in the pointer of IF PTR = NULL
newly created node and make the new node as tail of the EXIT
linked list. In this way insertion at end is done in linked SET NEW_NODE = PTR
list.Insertion at end in singly linked list in C++, is one of SET PTR = PTR – > NEXT
the insertion operations that we can perform on Linked SET NEW_NODE – > DATA = VAL
List. Singly linked list in C++ are part of linked list and is a SET NEW_NODE – > NEXT = NULL
type of linear data structure. Linked is made up of two parts SET PTR = HEAD
node and pointer where node contains the data and pointer WHILE PTR – > NEXT != NULL
contains the address of the next node. SET PTR = PTR – > NEXT
SET PTR – > NEXT = NEW_NODE
EXIT

Singly linked list definition in C++ C++ program to insert an element at end of singly
Nodes of singly linked list is created by using the code linked list
mentioned besides. #include <iostream>
This set of code will construct linked list by creating each using namespace std;
node of the list. //creating the structure of a new node
struct node
class Node {
{ int num;
int data; node *nextptr;

90
}*stnode; }
else
void createList(int n) //function to create a linked list. {
{ tmp = stnode;
struct node *frntNode, *tmp; cout<<"Linked List: ";
int num, i; while(tmp != NULL)
{
stnode = (struct node *)malloc(sizeof(struct node)); cout<<"\t"<<tmp->num;
if(stnode == NULL) tmp = tmp->nextptr;
{ }
cout<<"Memory can not be allocated"; }
} }
else
{ void insertatEnd(int num)//function to add element at the
end
cout<<"Enter the data for node 1: "; {
cin>>num; struct node *frntNode, *tmp;
stnode-> num = num; frntNode = (struct node*)malloc(sizeof(struct node));
stnode-> nextptr = NULL; //Links the address field to if(frntNode == NULL)
NULL {
tmp = stnode; cout<<"Memory can not be allocated.";
}
for(i=2; i<=n; i++) else
{ {
frntNode = (struct node *)malloc(sizeof(struct frntNode->num = num; //Linking the data part
node)); frntNode->nextptr = NULL;
tmp = stnode;
while(tmp->nextptr != NULL)
if(frntNode == NULL) //If frntnode is null no tmp = tmp->nextptr;
memory cannot be allotted tmp->nextptr = frntNode; //Linking the address part
{ }
cout<<" Memory can not be allocated"; }
break;
}
else int main()
{ {
cout<<"Enter the data for node "<<i<<": "; // int n,num;
Entering data in nodes.
cin>>num; cout<<"Enter the number of nodes: ";
frntNode->num = num; cin>>n;
frntNode->nextptr = NULL; createList(n);
tmp->nextptr = frntNode; cout<<"\nLinked list data: \n";
tmp = tmp->nextptr; display();
} cout<<"\nEnter data you want to insert at the end: ";
} cin>>num;
} insertatEnd(num);
} cout<<"\nLinked list after insertion: \n";
display();
void display() //function to print linked list
{ return 0;
struct node *tmp; }
if(stnode == NULL)
{
cout<<" No data found in the list"; Insertion in between of nodes in singly linked list in C++

91
EXIT
SET NEW_NODE = PTR
Insertion in between the nodes in singly linked list in C++ NEW_NODE → DATA = VAL
How to perform insertion in between nodes in Singly SET TEMP = HEAD
Linked List in C++? SET I = 0
Insertion in between of nodes in singly linked lists in C++ REPEAT
is a multiple step process. In this article we will learn these TEMP = TEMP → NEXT
steps and algorithms for data insertion at desired positions. IF TEMP = NULL
EXIT
We can also perform insertion at beginning that is inserting PTR → NEXT = TEMP → NEXT
an element in the beginning of the linked list and insertion TEMP → NEXT = PTR
at end of the linked list. You can learn about this by SET PTR = NEW_NODE
clicking the button below EXIT
Program for insertion in between of nodes in singly linked
Insertion at beginning list in C++
Steps to insert an element in between of nodes in singly #include <iostream>
linked list using namespace std;
Following steps are followed for insertion of an element at
nth position in singly linked list. struct node
{
1.)If there is no data in the head then exit int num;
node *nextptr;
If(head==NULL) }*stnode; //node constructed
return
2.) Allocate space for a new node. void createList(int n);
void insertNode(int num, int pos);
new_node = (struct node *) malloc(sizeof(struct node *)); void display();
3.) In the space created for the new node, put the data in.
int main()
new_node->data = new_data {
4.)Traverse till the desired position and make the pointer of int n,num,pos;
the new node where the previous node is pointing.
cout<<"Enter the number of nodes: ";
new_node->ptr= prev_node->ptr cin>>n;
5.) Now point the pointer of the previous node to the new createList(n);
node. cout<<"\nLinked list data: \n";
display();
prev_node->ptr = new_node cout<<"\nEnter data you want to insert at the nth
Defining a singly linked list in C++ position: ";
Nodes of singly linked lists are created by using the code cin>>num;
mentioned besides. cout<<"Enter the position to insert new node : ";
This set of code will construct a linked list by creating each cin>>pos;
node of the list. insertNode( num, pos);
cout<<"\nLinked list after insertion: \n";
class Node display();
{
int data; return 0;
Node *next; }
}; void createList(int n) //function to create linked list.
Algorithm for insertion in between the nodes in singly {
linked list in c++ struct node *frntNode, *tmp;
Algorithm to insert an element at nth position of singly int num, i;
linked list
IF PTR = NULL stnode = (struct node *)malloc(sizeof(struct node));

92
if(stnode == NULL) tmp = stnode;
{ for(i=2; i<=pos-1; i++)
cout<<"Memory can not be allocated"; {
} tmp = tmp->nextptr;
else
{ if(tmp == NULL)
break;
cout<<"Enter the data for node 1: "; }
cin>>num; if(tmp != NULL)
stnode-> num = num; {
stnode-> nextptr = NULL; //Linking the address field frntNode->nextptr = tmp->nextptr; //Linking the
to NULL address part of new node
tmp = stnode; tmp->nextptr = frntNode;
}
for(i=2; i<=n; i++) else
{ {
frntNode = (struct node *)malloc(sizeof(struct cout<<"Data cannot be entered in that particular
node)); position\n";
}
}
if(frntNode == NULL) //If frntnode is null no }
memory cannot be allotted
{ void display() //function to print linked list
cout<<"Memory can not be allocated"; {
break; struct node *tmp;
} if(stnode == NULL)
else {
{ cout<<" No data found in the list";
cout<<"Enter the data for node "<<i<<": "; // }
Entering data in nodes. else
cin>>num; {
frntNode->num = num; tmp = stnode;
frntNode->nextptr = NULL; cout<<"Linked List: ";
tmp->nextptr = frntNode; while(tmp != NULL)
tmp = tmp->nextptr; {
} cout<<"\t"<<tmp->num;
} tmp = tmp->nextptr;
} }
} }
}
void insertNode(int num, int pos)//fuction to add node in Output:
desired position Enter the number of nodes: 4
{ Enter the data for node 1: 11
int i; Enter the data for node 2: 22
struct node *frntNode, *tmp; Enter the data for node 3: 33
frntNode = (struct node*)malloc(sizeof(struct node)); Enter the data for node 4: 44
if(frntNode == NULL)
{ Linked list data:
cout<<"Memory can not be allocated."; Linked List: 11 22 33 44
} Enter data you want to insert at the nth position: 55
else Enter the position to insert new node : 4
{
frntNode->num = num; //Linking the data Linked list after insertion: Linked List: 11 22
frntNode->nextptr = NULL; 33 55 44

93

You might also like