Data Structure Lab Manual
Data Structure Lab Manual
MCA
SEMESTER - I(CBCS)
1. Module I 01
2. Module II 21
3. Module III 45
4. Module IV 62
5. Module V 142
6. Module VI 177
F.Y. MCA
SEMESTER - I(CBCS)
DATA STRUCTURES LAB USING C/C++
Syllabus
03 Module: Stacks: 06
Array implementation, Linked List implementation,
Evaluation of postfix expression and balancing of
parenthesis
04 Module: Queue: 08
Linked List implementation of ordinary queue,
Array implementation of circular queue, Linked
List implementation of priority queue, Double
ended queue
Self Learning Topics : Other queue applications
07 Module: Graphs: 08
Represent a graph using the Adjacency Matrix,
BFS, Find the
minimum spanning tree (using any method
Kruskal’s Algorithm or Prim’s Algorithm)
Self Learning Topics : Shortest Path Algorithm
Module I
Practical No: 1
Example:
Let us consider an array A[] that has the following elements:
A[] = {30, 52, 29, 87, 63, 27, 19, 54}
Pass 1 :-
(a) Compare 30 and 52. Since 30 < 52, no swapping is done.
(b) Compare 52 and 29. Since 52 > 29, swapping is done.
30, 29, 52, 87, 63, 27, 19, 54
(c) Compare 52 and 87. Since 52 < 87, no swapping is done.
(d) Compare 87 and 63. Since 87 > 63, swapping is done.
30, 29, 52, 63, 87, 27, 19, 54
(e) Compare 87 and 27. Since 87 > 27, swapping is done.
30, 29, 52, 63, 27, 87, 19, 54
(f) Compare 87 and 19. Since 87 > 19, swapping is done.
30, 29, 52, 63, 27, 19, 87, 54
(g) Compare 87 and 54. Since 87 > 54, swapping is done.
30, 29, 52, 63, 27, 19, 54, 87
1
Observe that after the end of the first pass, the largest element is
placed at the highest index of the array. All the other elements are still
unsorted.
Pass 2 :-
(a) Compare 30 and 29. Since 30 > 29, swapping is done.
29, 30, 52, 63, 27, 19, 54, 87
(b) Compare 30 and 52. Since 30 < 52, no swapping is done.
(c) Compare 52 and 63. Since 52 < 63, no swapping is done.
(d) Compare 63 and 27. Since 63 > 27, swapping is done.
29, 30, 52, 27, 63, 19, 54, 87
(e) Compare 63 and 19. Since 63 > 19, swapping is done.
29, 30, 52, 27, 19, 63, 54, 87
(f) Compare 63 and 54. Since 63 > 54, swapping is done.
29, 30, 52, 27, 19, 54, 63, 87
Observe that after the end of the second pass, the second largest
element is placed at the second highest index of the array. All the other
elements are still unsorted.
Pass 3 :-
(a) Compare 29 and 30. Since 29 < 30, no swapping is done.
(b) Compare 30 and 52. Since 30 < 52, no swapping is done.
(c) Compare 52 and 27. Since 52 > 27, swapping is done.
29, 30, 27, 52, 19, 54, 63, 87
(d) Compare 52 and 19. Since 52 > 19, swapping is done.
29, 30, 27, 19, 52, 54, 63, 87
(e) Compare 52 and 54. Since 52 < 54, no swapping is done.
Observe that after the end of the third pass, the third largest element is
placed at the third highest index of the array. All the other elements are
still unsorted.
Pass 4 :-
(a) Compare 29 and 30. Since 29 < 30, no swapping is done.
(b) Compare 30 and 27. Since 30 > 27, swapping is done.
29, 27, 30, 19, 52, 54, 63, 87
(c) Compare 30 and 19. Since 30 > 19, swapping is done.
29, 27, 19, 30, 52, 54, 63, 87
(d) Compare 30 and 52. Since 30 < 52, no swapping is done.
Observe that after the end of the fourth pass, the fourth largest
element is placed at the fourth highest index of the array. All the other
elements are still unsorted.
2
Pass 5 :-
(a) Compare 29 and 27. Since 29 > 27, swapping is done.
27, 29, 19, 30, 52, 54, 63, 87
(b) Compare 29 and 19. Since 29 > 19, swapping is done.
27, 19, 29, 30, 52, 54, 63, 87
(c) Compare 29 and 30. Since 29 < 30, no swapping is done.
Observe that after the end of the fifth pass, the fifth largest element
is placed at the fifth highest index of the array. All the other elements are
still unsorted.
Pass 6 :-
(a) Compare 27 and 19. Since 27 > 19, swapping is done.
19, 27, 29, 30, 52, 54, 63, 87
(b) Compare 27 and 29. Since 27 < 29, no swapping is done.
Observe that after the end of the sixth pass, the sixth largest
element is placed at the sixth largest index of the array.
All the array elements are present in sorted order.
Algorithm:
BUBBLE_SORT(A, N)
Step 1: Repeat Step 2 For I= 0 to N-1 // to keep track of the number of
iterations
Step 2: Repeat For J= 0 to N-I // to compare the elements within the
particular iteration
Step 3: IF A[J] > A[J+1] // swap if any element is greater than its
adjacent element
SWAP A[J] and A[J+1]
[END OF INNER LOOP]
[END OF OUTER LOOP]
Step 4: EXIT
Program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, n, temp, j, arr[10];
printf("Enter the maximum elements you want to store : ");
scanf("%d", &n);
printf("Enter the elements \n");
for(i=0;i<n;i++)
{
scanf("%d", & arr[i]);
}
3
for(i=0;i<n;i++)
{
for(j=0;j<n-1;j++)
{
if(arr[j]>arr[j+1])
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
printf("The array sorted in ascending order is :\n");
for(i=0;i<n;i++)
printf("%d\t", arr[i]);
getch();
return 0;
}
Questions:
1. Assume that we use Bubble Sort to sort n distinct elements in ascending
order. When does the best case of Bubble Sort occur?
A. When elements are sorted in descending order
B. When elements are sorted in ascending order
C. When elements are not sorted by any order
D. There is no best case for Bubble Sort. It always takes O(n*n) time
4
Practical No: 2
Theory:
Insertion sort is a sorting algorithm that places an unsorted
element at its suitable place in each iteration. The array is virtually split
into a sorted and an unsorted part. Elements from the unsorted part are
picked and placed at the correct position in the sorted part. For example,
the lower part of an array is maintained to be sorted. An element which is
to be inserted in this sorted list, has to find its appropriate place and then it
has to be inserted there. Hence the name, insertion sort.
Example:
Another Example:
12, 11, 13, 5, 6
Let us loop for i = 1 (second element of the array) to 4 (last element of the
array)
Step 1: Since 11 is smaller than 12, move 12 and insert 11 before 12
11, 12, 13, 5, 6
Step 2:13 will remain at its position as all elements in A[0..i-1] are
smaller than 13
11, 12, 13, 5, 6
Step 3:5 will move to the beginning and all other elements from 11 to 13
will move one position ahead of their current position.
5, 11, 12, 13, 6
5
Step 4:6 will move to position after 5, and elements from 11 to 13 will
move one position ahead of their current position.
5, 6, 11, 12, 13
Algorithm:
INSERTION-SORT (ARR, N)
Step 1: Repeat Steps 2 to 5 for K = 1 to N-1
Step 2: SET TEMP = ARR[K]
Step 3: SET J = K - 1
Step 4: Repeat while TEMP <=ARR[J]
SET ARR[J + 1] = ARR[J]
SET J = J - 1
[END OF INNER LOOP]
Step 5: SET ARR[J + 1] = TEMP
[END OF LOOP]
Step 6: EXIT
Program:
#include<stdio.h>
#include<conio.h>
void main ()
{
int i, j, k,temp;
int a[10] = { 10, 9, 7, 101, 23, 44, 12, 78, 34, 23};
printf("\nprinting sorted elements...\n");
for(k=1; k<10; k++)
{
temp = a[k];
j= k-1;
while(j>=0 && temp <= a[j])
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = temp;
}
for(i=0;i<10;i++)
{
printf("\n%d\n",a[i]);
}
getch();
}
6
Questions:
1. What will be the number of passes to sort the elements using insertion
sort?
14, 12,16, 6, 3, 10
A. 6
B. 5
C. 7
D. 1
2. For the following question, how will the array elements look like after
second pass?
34, 8, 64, 51, 32, 21
A. 8, 21, 32, 34, 51, 64
B. 8, 32, 34, 51, 64, 21
C. 8, 34, 51, 64, 32, 21
D. 8, 34, 64, 51, 32, 21
Theory:
1. Selection sorting is conceptually the simplest sorting algorithm. This
algorithm first finds the smallest element in the array and exchanges it
7
with the element in the first position, then finds the second smallest
element and exchange it with the element in the second position, and
continues in this way until the entire array is sorted.
2. The idea behind this algorithm is that first divide the array into two
parts: sorted and unsorted. The left part is sorted subarray and the right
part is unsorted subarray. Initially, sorted subarray is empty and unsorted
array is the complete given array.Then perform the steps given below until
the unsorted subarray becomes empty:
i. Pick the minimum element from the unsorted subarray.
ii. Swap it with the leftmost element and that element becomes a part
of sorted subarray and will not be a part of unsorted subarray.
iii. This process continues moving unsorted array boundary by one
element to the right.
Example:
Consider the following array with 6 elements. Sort the elements of
the array by using selection sort.
A = {10, 2, 3, 90, 43, 56}
1 2 10 3 90 43 56
2 2 3 10 90 43 56
3 2 3 10 90 43 56
4 2 3 10 43 90 56
5 2 3 10 43 56 90
Algorithm:
SELECTION SORT(ARR, N)
Step 1: Repeat Steps 2 and 3 for K = 1 to N-1
Step 2: CALL SMALLEST(ARR, K, N, POS)
Step 3: SWAP A[K] with ARR[POS]
[END OF LOOP]
Step 4: EXIT
8
SMALLEST (ARR, K, N, POS)
Step 1: [INITIALIZE] SET SMALL = ARR[K]
Step 2: [INITIALIZE] SET POS = K
Step 3: Repeat for J = K+1 to N -1
IF SMALL > ARR[J]
SET SMALL = ARR[J]
SET POS = J
[END OF IF]
[END OF LOOP]
Step 4: RETURN POS
Program:
#include<stdio.h>
#include<conio.h>
int smallest(int[],int,int);
void main ()
{
int a[10] = {10, 9, 7, 101, 23, 44, 12, 78, 34, 23};
int i,j,k,pos,temp;
for(i=0;i<10;i++)
{
pos = smallest(a,10,i);
temp = a[i];
a[i]=a[pos];
a[pos] = temp;
}
printf("\nprinting sorted elements...\n");
for(i=0;i<10;i++)
{
printf("%d\n",a[i]);
}
}
int smallest(int a[], int n, int i)
{
int small,pos,j;
small = a[i];
pos = i;
for(j=i+1;j<10;j++)
{
if(a[j]<small)
{
small = a[j];
9
pos=j;
}
}
getch();
return pos;
}
Questions:
3. Which operation does the Selection sort use to move numbers from the
unsorted section to the sorted section of the list?
A. Swap
B. Sort
C. Insert
D. Merge
5. Selection sort the following array. Show the array after each swap that
takes place.
80, 65, 46, 32, 95, 30
10
Practical No: 4
Theory:
Shell sort algorithm is invented by Donald shell. Shell sort is a
highly efficient sorting algorithm. It is a variation of Insertion Sort. In
insertion sort, we move elements only one position ahead. When an
element has to be moved far ahead, many movements are involved. This
algorithm avoids large shifts. The idea of ShellSort is to allow exchange
of far items. It first sorts elements that are far apart from each other and
successively reduces the interval between the elements to be sorted. We
keep reducing the value of interval until it becomes 1.
Example:
Suppose, we need to sort the following array.
9 8 3 7 5 6 4 1
Step 1: In the first step, if the array size is N = 8 then, the elements lying
at the interval of N/2 = 4 are compared and swapped if they are not in
order.
a. The 0th element is compared with the 4th element.
b. If the 0th element is greater than the 4th one then, the 4th element
is first stored in temp variable and the 0th element (ie. greater
element) is stored in the 4th position and the element stored in
temp is stored in the 0th position.
This process goes on for all the remaining elements at N/2 interval i.e., 4
5 8 3 7 9 6 4 1
5 6 3 7 9 8 4 1
5 6 3 7 9 8 4 1
5 6 3 1 9 8 4 7
11
In the second step, an interval of N/4 = 8/4 = 2 is taken and again the
elements lying at these intervals are sorted.
Rearrange the elements at n/4 interval
5 6 3 1 9 8 4 7
3 6 5 1 9 8 4 7
All the elements in the array lying at the current interval are compared.
3 1 5 6 9 8 4 7
3 1 5 6 9 8 4 7
The elements at 4th and 2nd position are compared. The elements at 2nd
and 0th position is also compared. All the elements in the array lying at
the current interval are compared. The same process goes on for
remaining elements.
3 6 5 1 9 8 4 7
3 1 5 6 9 8 4 7
3 1 4 6 5 8 9 7
3 1 4 6 5 8 9 7
3 1 4 6 5 7 9 8
Finally, when the interval is N/8 = 8/8 =1 then the array elements lying at
the interval of 1 are sorted. The array is now completely sorted.
3 1 4 6 5 7 9 8
1 3 4 6 5 7 9 8
1 3 4 6 5 7 9 8
1 3 4 6 5 7 9 8
1 3 4 5 6 7 9 8
1 3 4 5 6 7 9 8
1 3 4 5 6 7 9 8
1 3 4 5 6 7 9 8
1 3 4 5 6 7 8 9
Algorithm:
Shell_Sort(Arr, n)
Step 1: SET FLAG = 1, GAP_SIZE = N
Step 2: Repeat Steps 3 to 6 while FLAG = 1 OR GAP_SIZE > 1
Step 3: SET FLAG = 0
Step 4: SET GAP_SIZE = (GAP_SIZE + 1) / 2
Step 5: Repeat Step 6 for I = 0 to I < (N -GAP_SIZE)
12
Step 6: IF Arr[I + GAP_SIZE] > Arr[I]
SWAP Arr[I + GAP_SIZE], Arr[I]
SET FLAG = 0
Step 7: END
Program:
#include <stdio.h>
#include <conio.h>
void shellsort(int arr[], int num)
{
int i, j, k, tmp;
for (i = num / 2; i > 0; i = i / 2)
{
for (j = i; j < num; j++)
{
for(k = j - i; k >= 0; k = k - i)
{
if (arr[k+i] >= arr[k])
break;
else
{
tmp = arr[k];
arr[k] = arr[k+i];
arr[k+i] = tmp;
}
}
}
}
}
int main()
{
int arr[30];
int k, num;
printf("Enter total no. of elements : ");
scanf("%d", &num);
printf("\nEnter %d numbers: ", num);
for (k = 0 ; k < num; k++)
{
scanf("%d", &arr[k]);
}
shellsort(arr, num);
printf("\n Sorted array is: ");
for (k = 0; k < num; k++)
13
printf("%d ", arr[k]);
return 0;
}
Questions:
1.Which of the following sorting algorithms is closely related to shell sort?
A. Selection sort
B. Merge sort
C. Insertion sort
D. Bucket sort
14
Practical No: 5
Theory:
Radix sort is one of the sorting algorithms used to sort a list of
integer numbers in order. In radix sort algorithm, a list of integer numbers
will be sorted based on the digits of individual numbers. Sorting is
performed from least significant digit to the most significant digit.
Suppose, we have an array of 8 elements. First, we will sort elements
based on the value of the unit place. Then, we will sort elements based on
the value of the tenth place. This process goes on until the last significant
place.
Radix sort algorithm requires the number of passes which are equal
to the number of digits present in the largest number among the list of
numbers. For example, if the largest number is a 3 digit number then that
list is sorted with 3 passes.
Example:
Sort the numbers given below using radix sort.
345, 654, 924, 123, 567, 472, 555, 808, 911
15
In the first pass, the numbers are sorted according to the digit at
ones place. The buckets are pictured upside down as shown below.
Number 0 1 2 3 4 5 6 7 8 9
345 345
654 654
123 123
567 567
472 472
555 555
808 808
911 911
After this pass, the numbers are collected bucket by bucket. The
new list thus formed is used as an input for the next pass. In the second
pass, the numbers are sorted according to the digit at the tens place. The
buckets are pictured upside down.
Number 0 1 2 3 4 5 6 7 8 9
911 911
472 472
123 123
654 654
345 345
555 555
567 567
808 808
16
In the third pass, the numbers are sorted according to the digit at
the hundreds place. The buckets are pictured upside down.
Number 0 1 2 3 4 5 6 7 8 9
808 808
911 911
123 123
345 345
654 654
555 555
567 567
472 472
The numbers are collected bucket by bucket. The new list thus
formed is the final sorted result. After the third pass, the list can be given
as
123, 345, 472, 555, 567, 654, 808, 911
Algorithm:
Step 1: Find the largest number in ARR as LARGE
Step 2: [INITIALIZE] SET NOP = Number of digits in LARGE
Step 3: SET PASS =0
Step 4: Repeat Step 5 while PASS <= NOP-1
Step 5: SET I = 0 and INITIALIZE buckets
Step 6: Repeat Steps 7 to 9 while I
Step 7: SET DIGIT = digit at Passth place in A[I]
Step 8: Add A[I] to the bucket numbered DIGIT
Step 9: INCREMENT bucket count for bucket numbered DIGIT
[END OF LOOP]
Step 10: Collect the numbers in the bucket
[END OF LOOP]
Step 11: END
Program:
#include <stdio.h>
#include <conio.h>
int largest(int a[]);
void radix_sort(int a[]);
void main()
{
17
int i;
int a[10]={90,23,101,45,65,23,67,89,34,23};
radix_sort(a);
printf("\n The sorted array is: \n");
for(i=0;i<10;i++)
printf(" %d\t", a[i]);
}
Questions:
1. Given a number of elements in the range [0….n^3]. which of the
following sorting algorithms can sort them in O(n) time?
A. Counting sort
B. Bucket sort
C. Radix sort
D. Quick sort
3. Given an array where numbers are in range from 1 to n6, which sorting
algorithm can be used to sort these number in linear time?
A. Not possible to sort in linear time
B. Radix Sort
C. Counting Sort
D. Quick Sort
Self-Learning Topic:
Quick sort:
Quicksort is a sorting algorithm based on the divide and conquer approach
where an array is divided into subarrays by selecting a pivot element.The
left and right subarrays are also divided using the same approach. This
process continues until each subarray contains a single element.Finally,
elements are combined to form a sorted array.
20
Module II
Practical No: 1
Theory:
Linear search is the simplest search algorithm and often called
sequential search. In this type of searching, we simply traverse the list
completely and match each element of the list with the item whose
location is to be found. If the match is found then location of the item is
returned otherwise the algorithm returns no element found. Linear search
is mostly used to search an unordered list in which the items are not
sorted. As Linear search compares each and every element one by one i.e.,
it requires more time as compared to other search algorithms.
Example:
If an array A[] is declared and initialized as,
int A[] = {10, 8, 1, 21, 7, 32, 5, 11, 0}
Algorithm:
LINEAR_SEARCH(A, N, VAL)
Step 1: [Initialize] set pos = -1
Step 2: [Initialize] set i = 1
Step 3: Repeat Step 4 while I<=N
Step 4:If a[i] = val
Set pos = i
21
Print pos
Go to step 6
[End of if]
Set i = i + 1
[End of loop]
Program:
#include<stdio.h>
#include<conio.h>
void main ()
{
int a[10] = {10, 23, 40, 1, 2, 0, 14, 13, 50, 9};
int item, i, flag;
printf("\nEnter Item which is to be searched\n");
scanf("%d",&item);
for (i = 0; i< 10; i++)
{
if(a[i] == item)
{
flag = i+1;
break;
}
else
{
flag = 0;
}
}
if(flag != 0)
{
printf("\nItem found at location %d\n",flag);
}
else
{
printf("\nItem not found\n");
}
getch();
}
22
Questions:
1. Which of the following is a disadvantage of linear search?
A. Requires more space
B. Requires more time for searching
C. Not easy to understand
D. Not easy to implement
Practical No: 2
Theory:
Binary search is the search technique which works efficiently on
the sorted lists. Hence, in order to search an element into some list by
using binary search technique, we must ensure that the list is sorted. But it
23
cannot be applied to linked list. Binary search follows divide and conquer
approach in which, the list is divided into two halves and the item is
compared with the middle element of the list. If the match is found then,
the location of middle element is returned. If the middle item is greater
than the item, then the item is searched in the sub-array to the left of the
middle item. Otherwise, the item is searched in the sub-array to the right
of the middle item.
Example:
Let us consider an array a = {11, 15, 17, 18, 23, 29, 30, 33, 39}.
Find the location of the item 33 in the array.
Elements 11 15 17 18 23 29 30 33 39
Indexes 0 1 2 3 4 5 6 7 8
Step 1:
BEG = 0
END = 8
MID = (BEG+END)/2= (0+8)/2= 4
a[MID] = a[4] = 23 < 33
Step 2:
BEG = MID +1 = 4+1= 5
END = 8
MID = (BEG+END)/2= (5+8)/2= 13/2 = 6
a[MID] = a[6] = 30 < 33
Step 3:
BEG = MID + 1 = 6+1= 7
END = 8
MID = (BEG+END)/2= (7+8)/2= 15/2 = 7
a[MID] = a[7]
a[7] = 33 = item;
Therefore, the location of the item will be 7.
Algorithm:
Step 1: Find the middle element in the sorted list.
Step 2: Compare the search element with the middle element in the sorted
list.
Step 3: If both are matched, then display "Given element is found!" and
terminate the function.
Step 4: If both are not matched, then check whether the search element is
smaller or larger than the middle element.
24
Step 5: If the search element is smaller than middle element, repeat steps
2, 3, 4 and 5 for the left sublist of the middle element.
Step 6: If the search element is larger than middle element, repeat steps 2,
3, 4 and 5 for the right sublist of the middle element.
Step 7: Repeat the same process until we find the search element in the list
or until sublist contains only one element.
Step 8: If that element also doesn't match with the search element, then
display "Element is not found in the list" and terminate the function.
Program:
#include<stdio.h>
#include<conio.h>
void main()
{
int first, last, middle, size, i, key, list[100];
clrscr();
printf("Enter the size of the list: ");
scanf("%d",& size);
printf("Enter %d integer values in Ascending order\n", size);
for (i = 0; i < size; i++)
{
scanf("%d",&list[i]);
}
printf("Enter value to be search: ");
scanf("%d", &key);
first = 0;
last = size - 1;
middle = (first+last)/2;
while (first <= last)
{
if (list[middle] <key)
{
first = middle + 1;
}
else if (list[middle] == key)
{
printf("Element found at index %d.\n",middle);
break;
}
else
{
last = middle - 1;}
25
middle = (first + last)/2;
}
if (first > last)
{
printf("Element Not found in the list.");
}
getch();
}
Questions:
1. Binary Search can be categorized into which of the following?
A. Brute Force technique
B. Divide and conquer
C. Greedy algorithm
D. Dynamic programming
4. Search element 500 from the given array using binary search algorithm.
50, 60, 150, 280, 320, 400, 500, 600
Practical No: 3
Theory:
Hashing is a technique or process of mapping keys, values into the
hash table by using a hash function. It is done for faster access to
elements. Modulo Division is the easiest method to create a hash function.
26
Also known as division remainder, the modulo-division method divides
the key by table size and uses the remainder for the address. The hash
function can be described as
h(k) = k mod m
Here, h(k) is the hash value obtained by dividing the key value k by size of
hash table m using the remainder.
Example:
Elements to be placed in a hash table are 42,78,89,64 and let’s take table
size as 10.
Hash (key) = Elements % table size;
h(k)= k mod m
h(42) = 42 % 10 = 2
h(78) = 78 % 10 = 8
h(89) = 89 % 10 = 9
h(64) = 64 % 10 = 4
The table representation can be seen as below:
Key Value
0
1
2 42
3
4 64
5
6
7
8 78
9 89
Algorithm:
Suppose array name is A and n is the size of array.
Step 1: Initialize all array values with -1.
Step 2: Specify the values which needs to be inserted.
Step 3: Calculate key address using modulo division method.
Set key= value % size
Step 4: If A[key] = = -1
Set A[key] = value // Insert the value at calculated key or address
27
Else
Print: Unable to insert
[End If]
Step 5: If A[key] = = value
Print: Search found
Else
Print: Search not found
[End If]
Step 6: Repeat while key< n
Print: A[key]
[End while]
Step 7: End
Program:
#include<stdio.h>
#include<conio.h>
#define size 7
int arr[size];
void init()
{
int i;
for(i = 0; i < size; i++)
{
arr[i] = -1;
}
}
void display()
{
int i;
for(i = 0; i < size; i++)
{
printf("arr[%d] = %d\n",i,arr[i]);
}
}
int main()
{
init();
insert(10); //key = 10 % 7 ==> 3
insert(4); //key = 4 % 7 ==> 4
insert(2); //key = 2 % 7 ==> 2
insert(3); //key = 3 % 7 ==> 3 (collision)
printf("Hash table\n");
display();
printf("\n");
printf("Searching value 4..\n");
search(4);
getch();
return 0;
}
Questions:
1. What is the hash function used in the division method?
A. h(k) = k/m
B. h(k) = k mod m
C. h(k) = m/k
D. h(k) = m mod k
29
2. What can be the value of m in the division method?
A. Any prime number
B. Any even number
C. 2p – 1
D. 2p
3. Using division method, in a given hash table of size 157, the key of
value 172 be placed at position _________.
A. 19
B. 72
C. 15
D. 17
Practical No: 4
Key Address
397425 374
235678 256
30
Example:
Ex: 123,42,56 and Table size = 9
H(123) =1 //First digit i.e. 1 is selected
H(42) = 4 //First digit i.e. 4 is selected
H(56) = 5 //First digit i.e. 5 is selected
Address Key
0
1 123
2
3
4 42
5 56
6
7
8
Algorithm:
Step 1: Begin
Step 2: Pass key value ‘Key’ as an argument to digit_extraction().
Step 3: Initialize values
Set: first_digit=0 and fouth_digit=0 //for extracting digit at first &
fourth position
Step 4: For extracting first digit from given no
Calculate: first_digit= key%10000000;
first_digit=first_digit/1000000;
Step 5: For extracting fourth digit from given no
Calculate: fourth_digit= key%1000;
fourth_digit=fourth_digit/100;
Step 6: Display the hashed location where given number will be stored.
Print: (first_digit, fourth_digit);
Step 7:End
Program:
#include<stdio.h>
int digit_extraction(int key)
{
int key_length=0;
int first_digit=0;
int fourth_digit=0;
first_digit= key%10000000;
first_digit=first_digit/1000000;
fourth_digit= key%1000;
31
fourth_digit=fourth_digit/100;
printf("%d key would be hashed at location %d%d
\n",key,first_digit, fourth_digit);
}
int main()
{
digit_extraction(1347878); //18
digit_extraction(1234678); //16
return 0;
}
Questions:
1. In ________ method of hashing, selected digits are extracted from the
key and used as the address.
A. Subtraction
B. Digit extraction
C. Rotation
D. Folding
3. If key is 987654 then using the odd-place digits, the index(hash value)
would be ________.
A. 486
B. 864
C. 975
D. 987
4. If key is 356487 then using the even-place digits, the index(hash value)
would be ________.
A. 368
B. 547
C. 648
D. 354
32
Practical No: 5
Theory:
In fold shift the key value is divided into parts whose size matches
the size of the required address. Then the left and right parts are shifted
and added with the middle part.The folding method works in the following
two steps:
Step 1: Divide the key value into a number of parts. That is, divide k into
parts k1, k2, …, kn, where each part has the same number of digits except
the last part which may have lesser digits than the other parts.
Step 2: Add the individual parts. That is, obtain the sum of k1 + k2 + … +
kn. The hash value is produced by ignoring the last carry, if any.
Example:
Suppose to calculate hash value for X = 5678 and hash table size 100, we
need to follow below steps:
Step 1: The X will be divided into two parts each having two digits i.e.
k1=56 and k2 = 78
Step 2: Adding all key parts
k1 + k2 i.e.
Key= 56 + 78 = 134
After ignoring the carry 1 (because here only two digits are
required as hash value) the resulting hash value for 5678 is 34.
Algorithm:
Step 1:The folding method is used for creating hash functions starts with
the item being divided into equal-sized pieces i.e., the last piece may not
be of equal size.
Step 2:The outcome of adding these bits together is the hash value, H(x) =
(a + b + c) mod M, where a, b, and c represent the preconditioned key
broken down into three parts and M is the table size, and mod stands for
modulo.
Step 3:In other words, the sum of three parts of the preconditioned key is
divided by the table size. The remainder is the hash key.
33
Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include <math.h>
int count_digits(int key)
{
int count=0;
while(key != 0)
{
key /= 10;
++count;
}
return count;
}
int main()
{
34
clrscr();
printf("\n\n%d",fold_shift(12789, 3)); //216
printf("\n\n%d",fold_shift(12345678, 1)); //6
printf("\n\n%d",fold_shift(5678, 2)); //34
getch();
return 0;
}
Questions:
1. For key 345678123 what will be index in fold shift?
A. 146
B. 641
C. 542
D. 678
4. If the number is 164257408 and table size is 100 then the location
where number will get stored by fold shift method is _________.
A. 6
B. 3
C. 56
D. 63
5. If the number is 123456789 and table size is 1000 then address where
number will get stored by foldshift method is __________.
A. 8
B. 138
C. 368
D. 20
35
Practical No: 6
Theory:
In fold boundary the left and right numbers are folded on a fixed boundary
between them and the center number. The two outside values are thus
reversed.
Step 2:Reverse left and right individual parts. Then, obtain the sum of
reversed parts and middle part if it exists. The hash value is produced by
ignoring the last carry, if any.
Example:
Suppose to calculate hash value for Key = 123456789 and size of required
address is 3 digits, we need to follow below steps:
Step 1: The Key will be divided into two parts
Key = 123 | 456 | 789
Step 2:Reverse left and right parts and add it with middle part.
321 (folding applied)+456+987 (folding applied) = 1764(discard 1
or 4)
After we ignore the carry 1 (because here only three digits are
required as hash value) the resulting hash value for 123456789 is 764.
Algorithm:
Step 1: Specify the number which is to be folded and boundary between
them.
fold_boundary(int key, int size)
Step 2: Initialize all the integer values.
Set: key_sum=0, key_frac=0, middle=0, left=0, right=0, digits=0,
key_length=0
Set: key_roll=key & fraction = size
36
Step 3: Calculate key_length
count_digits(key)
a. Initialize count with value zero
b. Repeat while (key!=0)
Key/=10;
++count
[End while]
c. Return count
d. Terminate function
Step 4: Divide the number in three parts around a fixed boundary on left
and right side.
Step 5: Compute first three digits of given number. Reverse it and store
the reversed value in left variable.
Step 6: Compute last three digits of the given number. Reverse it and store
the reversed value in right variable.
Step 7: Find middle value of the given number and store it in variable
middle.
Step 8: Calculate key_sum
key_sum = left + middle + right
Step 9: If carry is generated then ignore carry
Set: key_sum= key_sum % (int)pow(10, (fraction))
Step 10: Print: key_sum
Step 11: End
Program:
#include<stdio.h>
#include<string.h>
#include <math.h>
int count_digits(int key)
{
int count=0;
while(key != 0)
{
key /= 10;
++count;
}
return count;
}
37
{
int key_roll=key;
int key_sum=0;
int key_frac=0;
int middle=0;
int left=0;
int right=0;
int digits=0;
int key_length=0;
int fraction = size;
key_length = count_digits(key_roll);
key_frac = key_roll / (int)pow(10, (key_length - fraction));// start digit
left=reversDigits(key_frac);
key_roll = key_roll % (int)pow(10,3);
right=reversDigits(key_roll);
digits = (int)log10(key) + 1;
middle= (int)(key / pow(10, digits/ 2)) % 10;
key_sum = left +middle+ right;
return key_sum % (int)pow(10, (fraction)); //ignore carry
}
int main()
{
printf("\n\n%d",fold_boundary(3347878, 3)); //318
printf("\n\n%d",fold_boundary(1234678, 3)); //201
return 0;
}
38
Questions:
1. In which of the following, the left and right numbers are reversed on
except the center number?
A. Division method
B. fold boundary
C. fold shift
D. folding method
Practical No: 7
Theory:
Linear probing is one of the collision resolution techniques
classified under open addressing technique/Closed Hashing which is a
method for handling collisions. While hashing if two or more key points to
the same hash index under some modulo M it is called as collision. When
collision occurs, we linearly probe for the next slot. We keep probing until
an empty slot is found. The main problem with linear probing is
clustering. Many consecutive elements form groups.
39
Steps for collision resolution using linear probing are as follows.
Step 1: Calculate the hash key.
address = key % size;
Step 2: If hashTable[key] is empty, store the value directly.
hashTable[key] = data.
If the hash index already has some value, check for next index.
Next address = (key+1) % size;
If the next index is available hashTable[key], store the value.
Otherwise try for next index.
h(k) = (key+i) % size; where i= 0,1,2,3,…
Step 3:Do the above process till we find the space.
Example:
Let us consider a simple hash function as “key mod 7” and a sequence of
keys as 50, 700, 76, 85, 92. Hash them and if collision occurs resolve it
with linear probing.
1) Initially empty table
Key
Location 0 1 2 3 4 5 6
2) Insert 50:
h(k)= key % 7, h(50) = 50 % 7 = 1
Key 50
Location 0 1 2 3 4 5 6
3) Insert 700:
h(k)= key % 7, h(700) = 700 % 7 = 0
Key 700 50
Location 0 1 2 3 4 5 6
4) Insert 76:
h(k)= key % 7, h(76) = 76 % 7 = 6
Key 700 50 76
Location 0 1 2 3 4 5 6
5) Insert 85:
h(k)= key % 7, h(85) = 85 % 7 = 1 //Collision occurs as 50 is already
present at location 1 i.e. Find next location i.e.
h(k ̍) =(key + 1) % 7, h(85 ̍)= (85+1)%7= 2 //insert 85 at location 2
Key 700 50 85 76
Location 0 1 2 3 4 5 6
40
6) Insert 92:
h(k)= key % 7 = 92 % 7 = 1 //Collision occurs as 50 is already present at
location 1, Find next location i.e.
h(k ̍) =(key + 1) % 7= (92+1)%7= 2 //Collision occurs as 85 is already
present at location 2, Find next location i.e.
h(k ̍) =(key + 2) % 7= (92+2)%7= 3 //insert 92 at location 3
Key 700 50 85 92 76
Location 0 1 2 3 4 5 6
Algorithm:
Consider x is original array of elements, n is total no of elements in x, and
ht is hash table array.
Step 1: Enter total no of elements to store and enter those elements.
Accept: n and values of x[i]
Step 2: Initialize empty hash table, Repeat while i < size
Set ht[i]=-1 //empty hash table
Step 3: Repeat while i< n
Set key= x[i];
Set address=modulodivision(key)
If address not equals to -1
Set address= linearprobe(address)
else
Set address=key
[End If]
[End while]
Step 4: End
modulodivision(key)
Step 1: Calculate address as
address= key%size+1
Step 2: If address equal to size of hash table
Set address=0
Else
Return address
[End If]
linearprobe(address)
Step 1:Repeat while address in hash table is not empty
Find next address
If address == size //address equals to last address of hash
table
Set address = 0 //point address to first address in
hash table
41
[End If]
[End while]
Step 2: Return Address
Program:
#include <stdio.h>
#include <conio.h>
#define size 10
int ht[size];
void store(int x[ ], int n);
int modulodivision(int key);
int linearprobe(int address);
void main()
{
int i, n, x[10] ;
char ch ;
clrscr();
printf("Enter the number of elements: ") ;
scanf("%d",&n) ;
printf("Enter the elements:\n") ;
for(i=0 ; i<n ; i++)
{
scanf("%d",&x[i]) ;
}
store(x,n) ;
printf("Hashtable is as shown:\n") ;
for(i=0 ; i<size ; i++)
{
printf("%d ", ht[i]) ;
}
getch() ;
}
/* Hash Function */
int modulodivision(int key)
{
int address;
address=key%size+1;
if(address==size)
{
return 0;
}
else
{
return address;
}
}
/* Collision Resolution */
int linearprobe(int address)
{
while(ht[address]!=-1)
{
address++;
if(address==size)
address=0;
}
return address;
}
Questions:
43
2. ___________ is not a theoretical problem but actually occurs in real
implementations of probing.
A. Hashing
B. Clustering
C. Rehashing
D. Collision
3. Consider a 13-element hash table for which h(k)= key mod 13 is used
with integer keys. Assuming linear probing is used for collision resolution,
at which location would the key 103 be inserted, if the keys 661, 182, 24
and 103 are inserted in that order?
A. 0
B. 1
C. 11
D. 12
Self-Learning Topics:
Direct and Subtraction hashing:
In direct hashing the key is the address without any algorithmic
manipulation.
Direct hashing is limited and not suitable for large key values, but
it can be very powerful because it guarantees that there are no collisions.
In Subtraction hashing a fixed number is subtracted from key. It is suitable
for small list.
44
Module III
Practical No: 1
Theory:
A Stack is a linear data structure that follows the Last-In-First-
Out(LIFO) principle. It can be defined as a container in which insertion
and deletion can be done from the one end known as the top of the stack.
A stack data structure can be implemented using a one-dimensional array.
But stack implemented using array stores only a fixed number of data
values. Just define a one-dimensional array of specific size and insert or
delete the values into that array by using LIFO principle with the help of a
variable called 'top'. Initially, the top is set to -1. Whenever we want to
insert a value into the stack, increment the top value by one and then
insert. Whenever we want to delete a value from the stack, then delete the
top value and decrement the top value by one.
45
Algorithm:
1. Algorithm for push operation:
begin
if top = n then stack full
top = top + 1
stack (top) : = item;
end
2. Algorithm for pop operation:
begin
if top = 0 then stack empty;
item := stack(top);
top = top - 1;
end;
Program:
#include <stdio.h>
int stack[100],i,j,choice=0,n,top=-1;
void push();
void pop();
void show();
void main ()
{
printf("Enter the number of elements in the stack ");
scanf("%d",&n);
printf("***Stack operations using array***");
printf("\n---------------------------------\n");
while(choice != 4)
{
printf("Chose one from the below options...\n");
printf("\n1.Push\n2.Pop\n3.Show\n4.Exit");
printf("\n Enter your choice \n");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
push();
break;
}
case 2:
{
pop();
break;
}
46
case 3:
{
show();
break;
}
case 4:
{
printf("Exiting....");
break;
}
default:
{
printf("Please Enter valid choice ");
}
}
}
}
void push ()
{
int val;
if (top == n )
printf("\n Overflow");
else
{
printf("Enter the value?");
scanf("%d",&val);
top = top +1;
stack[top] = val;
}
}
void pop ()
{
if(top == -1)
printf("Underflow");
else
top = top -1;
}
void show()
{
for (i=top;i>=0;i--)
{
printf("%d\n",stack[i]);
47
}
if(top == -1)
{
printf("Stack is empty");
}
}
Questions:
1. What does ‘stack underflow’ refers to?
A. Accessing item from an undefined stack
B. Adding items to a full stack
C. Removing items from an empty stack
D. Index out of bounds exception
3. Which of the following array element will return the top of the stack
element for a stack of size n elements?
A. S[n-1]
B. S[n]
C. S[n-2]
D. S[n+1]
48
Practical No: 2
Theory:
The major problem with the stack implemented using an array is, it
works only for a fixed number of data values. Stack implemented using an
array is not suitable, when we don't know the size of data which we are
going to use. The stack implemented using linked list can work for an
unlimited number of values. That means, stack implemented using linked
list works for the variable size of data. So, there is no need to fix the size
at the beginning of the implementation. In linked list implementation of a
stack, every newly inserted element is pointed by 'top'. Whenever we want
to remove an element from the stack, simply remove the node which is
pointed by 'top' by moving 'top' to its previous node in the list. The next
field of the first element must be always NULL.
2. pop(): We can use the following steps to pop an element from the stack.
Step 1: Check whether stack is empty (top == NULL).
Step 2: If it is empty, then display "EMPTY STACK"
Step 3: If it is not empty, then create a temporary node and set it to TOP.
Step 4: Print the data of TOP.
Step 5: Make TOP to point to the next node.
Step 6: Delete the temporary node.
Algorithm:
1. Algorithm for push() operation:
begin
if (TOP == NULL) //Check whether stack is Empty
newNode -> next = NULL //if stack is empty
else
newNode -> next = TOP //if stack is not empty
49
TOP= newNode
end
Program:
#include<stdio.h>
#include<stdlib.h>
/* Structure to create a node with data and pointer */
struct Node
{
int data;
struct Node *next;
}
*top = NULL; // Initially the list is empty
void push(int);
void pop();
void display();
int main()
{
int choice, value;
printf("\nIMPLEMENTING STACKS USING LINKED LISTS\n");
while(1)
{
printf("1. Push\n2. Pop\n3. Display\n4. Exit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("\nEnter the value to insert: ");
scanf("%d", &value);
push(value);
break;
50
case 2: pop();
break;
case 3: display();
break;
case 4: exit(0);
break;
void pop()
{
if(top == NULL)
printf("\nEMPTY STACK\n");
else{
struct Node *temp = top;
printf("\nPopped Element : %d", temp->data);
printf("\n");
top = temp->next; // After popping, make the next node as TOP
free(temp);
}
}
void display()
{
if(top == NULL)
printf("\nEMPTY STACK\n");
else
51
{
printf("The stack is \n");
struct Node *temp = top;
while(temp->next != NULL){
printf("%d--->",temp->data);
temp = temp -> next;
}
printf("%d--->NULL\n\n",temp->data);
}
}
Questions:
1. If the size of the stack is 8 and we try to add the 9th element in the stack
then the condition is known as __________.
A. Underflow
B. Garbage collection
C. Overflow
D. Empty
2. If the elements '10', '20', '30' and '40' are added in a stack, so what
would be the order for the removal?
A. 10, 20, 30, 40
B. 20, 10, 30, 40
C. 40, 30, 20, 10
D. 30, 10, 20, 40
52
Practical No: 3
Theory:
The Postfix notation is used to represent algebraic
expressions.Reverse Polish notation, also known as Polish postfix notation
or simply postfix notation, is a mathematical notation in which operators
follow their operands. The expressions written in postfix form are
evaluated faster compared to infix notation as parenthesis are not required
in postfix.
Example:
Let us consider the given expression as 2 3 1 * + 9 -
We scan all elements one by one.
Character Stack
Step Operation Calculation
Scanned Status
1 2 Push 2
2 3 Push 2,3
3 1 Push 2,3,1 3*1=3
Pop 2 elements &
4 * 2,3
evaluate
Pop 2 elements &
5 + 5 2+3=5
evaluate
6 9 Push 5,9
Pop 2 elements &
7 - -4 5-9= -4
evaluate
Explanation:
1) Scan ‘2’, it’s a number, so push it to stack. Stack contains ‘2’
2) Scan ‘3’, again a number, push it to stack, stack now contains ‘2 3’.
3) Scan ‘1’, again a number, push it to stack, stack now contains ‘2 3 1’
4) Scan ‘*’, it’s an operator, pop two operands from stack, apply the *
operator on operands, we get 3*1 which results in 3. We push the
result ‘3’ to stack. Stack now becomes ‘2 3’.
5) Scan ‘+’, it’s an operator, pop two operands from stack, apply the +
operator on operands, we get 3 + 2 which results in 5. We push the
result ‘5’ to stack. Stack now becomes ‘5’.
53
6) Scan ‘9’, it’s a number, we push it to the stack. Stack now becomes
‘5 9’.
7) Scan ‘-‘, it’s an operator, pop two operands from stack, apply the –
operator on operands, we get 5 – 9 which results in -4. We push the
result ‘-4’ to stack. Stack now becomes ‘-4’.
8) There are no more elements to scan, we return the top element from
stack (which is the only element left in stack).
Algorithm:
Step 1:Create a stack to store operands (or values).
Step 2:Scan the given expression and do following for every scanned
element.
a) If the element is a number, push it into the stack.
b) If the element is an operator, pop operands for the operator from
stack. Evaluate the operator and push the result back to the stack.
Step 3:When the expression is ended, the number in the stack is the final
answer.
Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define MAX 50 //max size defined
int stack[MAX]; //a global stack
char post[MAX]; //a global postfix stack
int top=-1; //initializing top to -1
void pushstack(int tmp); //push function
void evaluate(char c); //calculate function
void main()
{
int i,l;
//clrscr();
printf("Insert a postfix notation :: ");
gets(post); //getting a postfix expression
l=strlen(post); //string length
for(i=0;i<l;i++)
{
if(post[i]>='0' && post[i]<='9')
{
pushstack(i); //if the element is a number push it
}
if(post[i]=='+' || post[i]=='-' || post[i]=='*' ||
post[i]=='/' || post[i]=='^') //if element is an operator
54
{
evaluate(post[i]); //pass it to the evaluate
}
} //print the result from the top
printf("\n\nResult :: %d",stack[top]);
getch();
}
Questions:
1. Which of the following is an example for a postfix expression?
A. a*b(c+d)
B. abc*+de-+
C. +ab
D. a+b-c
4. Evaluate and write the result for the following postfix expression
abc*+de*f+g*+ where a=1, b=2, c=3, d=4, e=5, f=6, g=2.
A. 61
B .59
C. 60
D. 55
Theory:
A stack can be used for syntax verification of the arithmetic
expression for ensuring that for each left parenthesis in the expression
there is a corresponding right parenthesis.
Algorithm:
Algorithm to check balanced parenthesis
Step 1: Initialize a character stack. Set top pointer of stack to -1.
Step 2: Find length of input string using strlen function and store it in an
integer variable "length".
Step 3: Using a for loop, traverse input string from index 0 to length-1.
Step 4: a.If current character is open parenthesis, then push it inside stack.
b. If current character is closing parenthesis, then pop a character
from stack.
c. If stack is empty, then input string is invalid, it means there is
no matching opening parenthesis corresponding to closing parenthesis.
Step 5: After complete traversal of input string, If stack is empty then
input expression is a Valid expression otherwise Invalid.
Program:
#include<string.h>
#include<conio.h>
#define MAX 20
struct stack
{
char stk[MAX];
int top;
}s;
void pop()
{
58
if (s.top == - 1)
{
printf ("Stack is Empty\n");
}
else
{
s.top = s.top - 1; // Pop the char and decrement top
}
}
int main()
{
char exp[MAX];
int i = 0;
s.top = -1;
printf("\nINPUT THE EXPRESSION : ");
scanf("%s", exp);
for(i = 0;i < strlen(exp);i++)
{
if(exp[i] == '(' || exp[i] == '[' || exp[i] == '{')
{
push(exp[i]); // Push the open bracket
continue;
}
else if(exp[i] == ')' || exp[i] == ']' || exp[i] == '}') // If a closed
bracket is encountered
{
if(exp[i] == ')')
{
if(s.stk[s.top] == '(')
{
pop(); // Pop the stack until closed bracket is
found
}
else
{
printf("\nUNBALANCED
EXPRESSION\n");
break;
}
}
if(exp[i] == ']')
{
if(s.stk[s.top] == '[')
59
{
pop(); // Pop the stack until closed bracket is found
}
else
{
printf("\nUNBALANCED
EXPRESSION\n");
break;
}
}
if(exp[i] == '}')
{
if(s.stk[s.top] == '{')
{
pop(); // Pop the stack until closed bracket is found
}
else
{
printf("\nUNBALANCED
EXPRESSION\n");
break;
}
}
}
}
if(s.top == -1)
{
printf("\nBALANCED EXPRESSION\n"); // Finally if the
stack is empty, display that the expression is balanced
}
getch();
}
Questions:
60
2. Which is the most appropriate data structure for applying balancing of
parentheses algorithm?
A. Stack
B. Queue
C. Tree
D. Graph
Self-Learning Topic:
Conversion of infix notation to postfix notation:
When the operator is written in between the operands, then it is
known as infix notation. The postfix expression is an expression in which
the operator is written after the operands. Postfix notation is very easily
implemented and does not have overhead of parentheses and there is no
complication of precedence of one operator over the other. To convert
infix expression to postfix expression stack data structure will be used.
61
Module IV
Data structures
Form No .: 5
Objective: Get familiar with the List interface. Understand how to write a
matrix based on.
Theory:
● The individually linked list can be defined as the collection of
ordered sets of elements. The number of items may vary according
to the needs of the program. A node in the individual linked list
consists of two parts: data part and link part. The data part of the
node stores the actual information that will be represented by the
node, while the link part of the node stores the address of its
immediate successor.
● One-way strings or individually linked lists can only be traversed
in one direction. In other words, we can say that each node
contains only the next pointer, so we cannot traverse the list in the
reverse direction.
● Consider an example where the student's grades in three subjects
are stored in a linked list as shown in the figure.
In the figure above, the arrow represents the links. The data part of
each node contains the marks obtained by the student in the various
subjects. The last node in the list is identified by the null pointer in the
address part of the last node. We can have all the elements we need, in the
data part of the list.
62
Algorithm:
Insertion
In a single linked list, the insert operation can be performed in
three ways. Are the following...
1. Insert at the beginning of the list
2. Enter to the end of the list
3. Insert in a specific position in the list
deletion
In a single linked list, the delete operation can be performed in
three ways. Are the following...
1. Delete from the top of the list
2. Remove from the end of the list
3. Delete a specific node
64
● Step 1: Check if the list is empty (head == NULL)
● Step 2: If blank, display 'List is empty! Deletion is not possible and
the function ends.
● Step 3: If it is not empty, define a pointer to the 'temp' node and
initialize with head.
● Step 4: Check if the list has only one node (temperature → next
== NULL)
● Step 5: If TRUE, set head = NULL and remove the temperature
(setting the conditions of the empty list)
● Step 6: If FALSE, set head = temperature → nextand eliminates
temp.
65
● Step 3: If it is not empty, define two pointers to the node "temp1"
and "temp2" and initialize "temp1" with head.
● Step 4: Continue moving temp1 until you reach the exact node to
be removed or the last node. And each time, set 'temp2 = temp1'
before moving 'temp1' to your next node.
● Step 5: If the last node is reached, display 'The specified node is
not in the list! Cancellation is not possible !!! '. And finish the
show.
● Step 6: If the exact node we want to remove is reached, check if
the list has only one node or not
● Step 7: If the list has only one node and this is the node to remove,
set head = NULL and remove temp1 (free (temp1)).
● Step 8: If the list contains multiple nodes, check if temp1 is the
first node in the list (temp1 == head).
● Step 9: If temp1 is the first node, move your head to the next node
(head = head → forward) and remove temp1.
● Step 10: If temp1 is not the first node, check if it is the last node in
the list (temp1 → next == NULL).
● Step 11: If temp1 is the last node, configure temp2 → next =
NULL and remove temp1 (free (temp1)).
● Step 12: If temp1 is not the first node and not the last node, set
temp2 → next = temp1 → next and remove temp1 (free (temp1)).
66
Program:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void insertAtBeginning (int);
void insertAtEnd (int);
void insertBetween (int, int, int);
blank display ();
void removeBeginning ();
void removeEnd ();
void removeSpecific (int);
Structure node
{
int data;
struct Node * next;
} * head = NULL;
main vacuum ()
{
int choice, value, choice1, loc1, loc2;
clrscr ();
while (1) {
mainMenu: printf ("\ n \ n ****** MENU ****** \ n1. Insert \ n2. Show \
n3. Delete \ n4. Exit \ nEnter your choice:");
scanf ("% d", & option);
change (choice)
{
case 1: printf ("Insert the value to insert:");
scanf ("% d", & value);
while (1) {
printf ("Where do you want to enter: \ n1. At the beginning \ n2. At the
end \ n3. Enter \ nPlease enter your choice:");
67
scanf ("% d", & choice1);
switch (option 1)
{
case 1: insertAtBeginning (value);
break time;
case 2: insertAtEnd (value);
break time;
case 3: printf ("Insert the two values where you want to insert:");
scanf ("% d% d", & loc1, & loc2);
insertBetween (value, loc1, loc2);
break time;
default: printf ("\ nIncorrect entry! Try again! \ n \ n");
go to the main menu;
}
go to subMenuEnd;
}
submenu End:
break time;
case 2: display ();
break time;
case 3: printf ("How do you want to remove: \ n1. From the beginning \
n2. From the end \ n3. Specific \ nPlease enter your choice:");
scanf ("% d", & choice1);
switch (option 1)
{
case 1: removeBeginning ();
break time;
case 2: removeEnd ();
break time;
case 3: printf ("Enter the value you want to remove:");
scanf ("% d", & loc2);
68
removeSpecific (loc2);
break time;
default: printf ("\ nIncorrect entry! Try again! \ n \ n");
go to the main menu;
}
break time;
case 4: exit (0);
default: printf ("\ nIncorrect entry !!! Try again !! \ n \ n");
}}}
void insertAtBeginning (int value)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode-> data = value;
yes (head == NULL)
{
newNode-> next = NULL;
head = newNode;
}
the rest
{
newNode-> next = head;
head = newNode;
}
printf ("\ nA node entered !!! \ n");
}
void insertAtEnd (int value)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
69
newNode-> data = value;
newNode-> next = NULL;
yes (head == NULL)
head = newNode;
the rest
{
struct Node * temp = head;
while (temp-> next! = NULL)
temp = temp-> next;
temp-> next = newNode;
}
printf ("\ nA node entered !!! \ n");
}
void insertBetween (int value, int loc1, int loc2)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode-> data = value;
yes (head == NULL)
{
newNode-> next = NULL;
head = newNode;
}
the rest
{
struct Node * temp = head;
while (temp-> data! = loc1 && temp-> data! = loc2)
temp = temp-> next;
newNode-> next = temp-> next;
temp-> next = newNode;
70
}
printf ("\ nA node entered !!! \ n");
}
void removeBeginning ()
{
yes (head == NULL)
printf ("\ n \ nThe list is empty!");
the rest
{
struct Node * temp = head;
yes (header-> next == NULL)
{
head = NULL;
free (temperature);
}
the rest
{
head = temp-> next;
free (temperature);
printf ("\ nA node removed !!! \ n \ n");
}}}
void removeEnd ()
{
yes (head == NULL)
{
printf ("\ nThe list is empty! \ n");
}
the rest
{
71
struct Node * temp1 = head, * temp2;
yes (header-> next == NULL)
head = NULL;
the rest
{
while (temp1-> next! = NULL)
{
temp2 = temp1;
temp1 = temp1-> next;
}
temp2-> next = NULL;
}
free (temp1);
printf ("\ nA node removed !!! \ n \ n");
}
}
void removeSpecific (int delValue)
{
struct Node * temp1 = head, * temp2;
while (temp1-> data! = delValue)
{
if (temp1 -> next == NULL) {
printf ("\ nNo nodes found in the list !!!");
goto functionEnd;
}
temp2 = temp1;
temp1 = temp1 -> next;
}
temp2 -> next = temp1 -> next;
free (temp1);
72
printf ("\ nA node removed !!! \ n \ n");
End function:
}
blank screen ()
{
yes (head == NULL)
{
printf ("\ nThe list is empty \ n");
}
the rest
{
struct Node * temp = head;
printf ("\ n \ nThe elements of the list are - \ n");
while (temp-> next! = NULL)
{
printf ("% d --->", temp-> data);
temp = temp-> next;
}
printf ("% d ---> NULL", temp-> data);
}}
Production:
73
1) Search in an individually linked list
The search is performed to find the position of a particular item in
the list. Searching for any item in the list requires you to scroll through the
list and compare each item in the list with the specified item. If the
element matches one of the elements in the list, the function returns the
position of the element.
Algorithm:
● Step 1: SET PTR = HEAD
● Step 2: Set I = 0
● STEP 3: IF PTR = NULL
● WRITE "EMPTY LIST" GOTO STEP 8 END OF YES STEP 4:
REPEAT STEPS 5 TO 7 UNTIL PTR! = NULL
Program:
#include <stdio.h>
#include <stdlib.h>
empty create (int);
empty Research();
structure node
{
int data;
next structure node *;
};
knot structure * head;
empty principal ()
{
int choice, object, loc;
do
{
printf ("\ n1.Create \ n2.Search \ n3.Sexit \ n4.Enter your choice?");
74
scanf ("% d", & option);
change (choice)
{
Case 1:
printf ("\ nInsert element \ n");
scanf ("% d", & element);
create (element);
break time;
case 2:
Research();
case 3:
output (0);
break time;
default:
printf ("\ nPlease enter a valid option \ n");
}
} while (choice! = 3);
}
create empty (int element)
{
structure node * ptr = (structure node *) malloc (size of (structure node
*));
yes (ptr == NULL)
{
printf ("\ nOVERFLOW \ n");
}
the rest
{
ptr-> data = element;
ptr-> next = head;
head = ptr;
printf ("\ nNode inserted \ n");
75
}}
empty Research()
{
struct node * ptr;
int element, i = 0, flag;
ptr = head;
yes (ptr == NULL)
{
printf ("\ nEmpty list \ n");
}
the rest
{
printf ("\ nPlease enter the element you want to search for? \ n");
scanf ("% d", & element);
while (ptr! = NULL)
{
if (ptr-> data == element)
{
printf ("article found at location% d", i + 1);
flag = 0;
}
the rest
{
flag = 1;
}
i ++;
ptr = ptr -> next;
}
yes (flag == 1)
{
printf ("Item not found \ n");
}}}
76
Production:
78
empty createList (int n)
{
struct node * newNode, * temp;
int data, i;
head = (structure node *) malloc (size of (structure node));
/*
* If you cannot allocate memory for the head root node
*/
yes (head == NULL)
{
printf ("Unable to allocate memory");
}
the rest
{
/*
* Read data from user node
*/
printf ("Enter data for node 1:");
scanf ("% d", & data);
head-> data = data; // Link the data field with the data
head-> next = NULL; // Map the address field to NULL
temperature = head;
/*
* Create n nodes and add to linked list
*/
for (i = 2; i <= n; i ++)
{
newNode = (structure node *) malloc (size of (structure node));
/ * If no memory is allocated for newNode * /
yes (newNode == NULL)
{
printf ("Unable to allocate memory");
79
break time;
}
the rest
{
printf ("Insert data for node% d:", i);
scanf ("% d", & data);
newNode-> data = data; // Associate the data field of newNode with the
data
newNode-> next = NULL; // Associate the address field of newNode with
NULL
temp-> next = newNode; // Associate the previous node, ie temporarily
with the new node
temp = temp-> next;
}}
printf ("SIMPLE CONNECTED LIST CREATED SUCCESSFULLY \
n");
}}
/*
* Counts the total number of nodes in the list
*/
int countNodes ()
{
int count = 0;
struct node * temp;
temperature = head;
while (temp! = NULL)
{
count ++;
temp = temp-> next;
}
counting of returns;
}
/*
80
* Show the complete list
*/
empty displayList ()
{
struct node * temp;
/*
* If the list is empty, ie head = NULL
*/
yes (head == NULL)
{
printf ("The list is empty");
}
the rest
{
temperature = head;
while (temp! = NULL)
{
printf ("Data =% d \ n", temp-> data); // Print the data of the current node
temp = temp-> next; // Go to the next node
}}}
Production:
81
3) Reverse a linked list
Given a pointer to the parent node of a linked list, the task is to
reverse the linked list. We need to reverse the list by changing the links
between the nodes.
Examples of:
Entrance: Head of the next linked list
1-> 2-> 3-> 4-> NULL
Production: the linked list must be changed to,
4-> 3-> 2-> 1-> NULL
Entrance: Head of the next linked list
1-> 2-> 3-> 4-> 5-> NULL
Production: the linked list must be changed to,
5-> 4-> 3-> 2-> 1-> NULL
Entrance: NOTHING
Production: NOTHING
Entrance: 1-> NULL
Production: 1-> NULL
Iterative method
1. Initializes three pointers prev as NULL, curr as head and next as
NULL.
2. Iterate through the linked list. In a loop, do the following. // Before
changing the next one from the current one, // memorize the next node
next = curr-> next // Now change the next one from the current one //
This is where the actual inversion takes place curr-> next = previous //
Move previous and current one step forward previous = curr curr =
next
Program:
#include <iostream>
using the std namespace;
/ * Link List Node * /
node structure {
int data;
struct Node * next;
Node (int data)
82
{
this-> data = data;
next = NULL;
}
};
struct LinkedList {
Knot * head;
LinkedList () {head = NULL; }
83
struct Node * temp = head;
while (temp! = NULL) {
cout << temp-> data << "";
temp = temp-> next;
}
}
/ * Driver code * /
main integer ()
{
/ * Start with empty list * /
LinkedList ll;
ll.push (20);
ll. press (4);
ll.push (15);
ll.push (85);
84
returns 0;
}
Production:
Linked list given
85 15 4 20
Inverted linked list
20 4 15 85
Question:
1. What does the following function do for a given Linked List with
first node as head?
A. linked list
B. node list
C. primitive list
D. None of these
85
2. What is the output of the following function for starting pointing to the
first node of the following linked list? 1->2->3->4->5->6
A. Insertion sort
B. Radix sort
C. Polynomial manipulation
D. Binary search
86
Theory:
Example
Operations
In a circular linked list, we do the following ...
1. Insertion
2. deletion
3. Show
87
Insertion
In a circular linked list, the insert operation can be performed in three
ways. Are the following...
1. Insert at the beginning of the list
2. Enter to the end of the list
3. Insert in a specific position in the list
88
● Step 2: Check if the list is empty (head == NULL)
● Step 3: If empty, set head = newNode and newNode → next =
head.
● Step 4: If it is not empty, define a node pointer temperature and
initialize with head.
● Step 5: Keep moving the temperature on its next node until it
reaches the node after which we want to insert the new node (up to
temp1 → data is equal to location, here location is the value of the
node after which we want to insert the newNode).
● Step 6: Check each time if the temperature has been reached or not
until the last node. If the last node is reached, 'The specified node
is not in the list! Insertion not possible !!! 'and terminate the
function. Otherwise, move the temperature to the next node.
● Step 7: If the temperature you reach the exact node after which you
want to insert the newNode and then check if it is the last node
(temp → next == head).
● Step 8: If the temperature is the last knot, set temperature → next
= newNode e newNode → next = head.
● Step 8: If the temperature is not the last knot, set newNode → next
= temperature → next Yup temperature → next = newNode.
deletion
In a circular linked list, the delete operation can be performed in three
ways, which are as follows ...
1. Delete from the top of the list
2. Remove from the end of the list
3. Delete a specific node
89
● Step 5: If TRUE, set head = NULL and remove temp1 (setting
conditions of empty list)
● Step 6: If it is FALSE, move temp1 until it reaches the last node.
(as far astemp1 → next == head)
● Step 7: Then set the head = temp2 → next, temp1 → next = test
and clear temp2.
90
● Step 6: If the exact node we want to remove is reached, check if
the list has only one node (temp1 → next == head)
● Step 7: If the list has only one node and this is the node to remove,
set head = NULL and remove temp1 (free (temp1)).
● Step 8: If the list contains multiple nodes, check if temp1 is the
first node in the list (temp1 == head).
● Step 9: If temp1 is the first node, set temp2 = head and keep
moving temp2 to the next node until temp2 reaches the last node.
Then sethead = head → forward, temp2 → nextt = head and
delete temp1.
● Step 10: If temp1 is not the first node, check if it is the last node in
the list (temp1 → next == head).
● Step 1 1- If temp1 is the last node, configure temp2 → next =
head and remove temp1 (free (temp1)).
● Step 12: If temp1 is not the first node and not the last node, set
temp2 → next = temp1 → next and remove temp1 (free (temp1)).
Program:
#include <stdio.h>
#include <conio.h>
void insertAtBeginning (int);
void insertAtEnd (int);
void insertAtAfter (int, int);
void deleteBeginning ();
91
void deleteEnd ();
void deleteSpecific (int);
blank display ();
Structure node
{
int data;
struct Node * next;
} * head = NULL;
main vacuum ()
{
int choice1, choice2, value, position;
clrscr ();
while (1)
{
printf ("\ n *********** MENU ************* \ n");
printf ("1. Enter \ n2. Delete \ n3. Screen \ n4. Exit \ nEnter your
choice:");
scanf ("% d", & choice1);
Change ()
{
case 1: printf ("Insert the value to insert:");
scanf ("% d", & value);
while (1)
{
printf ("\ nSelect from the following insert options \ n");
printf ("1. At the beginning \ n2. At the end \ n3. After a node \ n4. Cancel
\ nEnter your choice:");
scanf ("% d", & choice2);
switch (option 2)
{
case 1: insertAtBeginning (value);
92
break time;
case 2: insertAtEnd (value);
break time;
case 3: printf ("Enter the position after which you want to insert:");
scanf ("% d", & location);
insertAfter (value, position);
break time;
case 4: go to EndSwitch;
default: printf ("\ nSelect the correct insert option! \ n");
}
}
case 2: while (1)
{
printf ("\ nSelect from the following delete options \ n");
printf ("1. At the beginning \ n2. At the end \ n3. Specific node \ n4.
Cancel \ nEnter your choice:");
scanf ("% d", & choice2);
switch (option 2)
{
case 1: deleteBeginning ();
break time;
case 2: deleteEnd ();
break time;
case 3: printf ("Enter the value of the node to be removed:");
scanf ("% d", & location);
deleteSpecic (location);
break time;
case 4: go to EndSwitch;
default: printf ("\ nSelect the correct delete option! \ n");
}
}
93
Limit switch: pause;
case 3: display ();
break time;
case 4: exit (0);
default: printf ("\ nSelect the correct option!");
}}}
void insertAtBeginning (int value)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
yes (head == NULL)
{
head = newNode;
newNode -> next = head;
}
the rest
{
struct Node * temp = head;
while (temp -> next! = head)
temp = temp -> next;
newNode -> next = head;
head = newNode;
temp -> next = head;
}
printf ("\ nThe entry was successful!");
}
void insertAtEnd (int value)
{
struct Node * newNode;
94
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
yes (head == NULL)
{
head = newNode;
newNode -> next = head;
}
the rest
{
struct Node * temp = head;
while (temp -> next! = head)
temp = temp -> next;
temp -> next = newNode;
newNode -> next = head;
}
printf ("\ nThe entry was successful!");
}
void insertAfter (int value, int location)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
yes (head == NULL)
{
head = newNode;
newNode -> next = head;
}
the rest
{
struct Node * temp = head;
95
while (temp -> data! = location)
{
yes (temp -> next == head)
{
printf ("The indicated node is not in the list !!!");
go to EndFunction;
}
the rest
{
temp = temp -> next;
}
}
newNode -> next = temp -> next;
temp -> next = newNode;
printf ("\ nThe entry was successful!");
}
Final function:
}
void deleteBeginning ()
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp = head;
yes (temp -> next == head)
{
head = NULL;
free (temperature);
}
96
the rest{
head = head -> forward;
free (temperature);
}
printf ("\ n Deletion successful !!!");
}
}
void deleteEnd ()
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp1 = head, temp2;
yes (temp1 -> next == head)
{
head = NULL;
free (temp1);
}
the rest{
while (temp1 -> next! = head) {
temp2 = temp1;
temp1 = temp1 -> next;
}
temp2 -> next = head;
free (temp1);
}
printf ("\ n Deletion successful !!!");
}
}
97
void deleteSpecific (int delValue)
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp1 = head, temp2;
while (temp1 -> data! = delValue)
{
yes (temp1 -> next == head)
{
printf ("\ nThe indicated node is not in the list !!!");
go to FineFunction;
}
the rest
{
temp2 = temp1;
temp1 = temp1 -> next;
}
}
if (temp1 -> next == head) {
head = NULL;
free (temp1);
}
the rest{
yes (temp1 == head)
{
temp2 = head;
while (temp2 -> next! = head)
temp2 = temp2 -> next;
98
head = head -> forward;
temp2 -> next = head;
free (temp1);
}
the rest
{
yes (temp1 -> next == head)
{
temp2 -> next = head;
}
the rest
{
temp2 -> next = temp1 -> next;
}
free (temp1);
}
}
printf ("\ n Deletion successful !!!");
}
End function:
}
blank screen ()
{
yes (head == NULL)
printf ("\ nList is empty !!!");
the rest
{
struct Node * temp = head;
printf ("\ nThe elements of the list are: \ n");
while (temp -> next! = head)
99
{
printf ("% d --->", temp -> data);
}
printf ("% d --->% d", temp -> data, test -> data);
}}
Production
Algorithm:
● Step 1: SET PTR = HEAD
● Step 2: Set I = 0
● STEP 3: IF PTR = NULL
● WRITE "EMPTY LIST" GO TO STEP 8 END YES
PHASE 4: IF HEAD → DATA = ARTICLE
● WRITE i + 1 RETURN [END OF S] STEP 5: REPEAT STEPS 5
TO 7 UNTIL PTR-> next! = Head
● STEP 6: if ptr → date = article
● write i + 1 RETURN of IF STEP 7: I = I + 1
100
Program:
#include <stdio.h>
#include <stdlib.h>
create void (int);
empty search ();
structure node
{
int data;
next structure node *;
};
knot structure * head;
main vacuum ()
{
int choice, object, loc;
do
{
printf ("\ n1.Create \ n2.Search \ n3.Sexit \ n4.Enter your choice?");
scanf ("% d", & option);
change (choice)
{
Case 1:
printf ("\ nInsert element \ n");
scanf ("% d", & element);
create (element);
break time;
case 2:
Research();
case 3:
output (0);
break time;
default:
printf ("\ nPlease enter a valid option \ n");
101
}
} while (choice! = 3);
}
create empty (int element)
{
structure node * ptr = (structure node *) malloc (size of (structure node));
struct node * temp;
yes (ptr == NULL)
{
printf ("\ nOVERFLOW \ n");
}
the rest
{
ptr-> data = element;
yes (head == NULL)
{
head = ptr;
ptr -> next = head;
}
the rest
{
temperature = head;
while (temp -> next! = head)
{
temp = temp -> next;
}
temp -> next = ptr;
ptr -> next = head;
}
printf ("\ nNode inserted \ n");
}}
stop searching ()
102
{
struct node * ptr;
int element, i = 0, flag = 1;
ptr = head;
yes (ptr == NULL)
{
printf ("\ nEmpty list \ n");
}
the rest
{
printf ("\ nPlease enter the element you want to search for? \ n");
scanf ("% d", & element);
if (head -> data == element)
{
printf ("article found at location% d", i + 1);
flag = 0;
come back;
}
the rest
{
while (ptr-> next! = head)
{
if (ptr-> data == element)
{
printf ("article found at location% d", i + 1);
flag = 0;
come back;
}
the rest
{
flag = 1;
}
103
i ++;
ptr = ptr -> next;
}}
yes (flag! = 0)
{
printf ("Item not found \ n");
come back;
}}}
Production:
104
Program:
#include <bit / stdc ++. h>
using the std namespace;
/ * structure for a node * /
node structure {
int data;
Next node *;
Node (int x)
{
data = x;
next = NULL;
}};
/ * Function to insert a node at the beginning
of a circular linked list * /
struct Node * push (struct Node * last, int data)
{
if (last == NULL) {
struct Node * temp
= (struct Node *) malloc (sizeof (struct Node));
// Assign the data.
temp-> data = data;
last = temperature;
105
// Note: The list was empty. We connect a single node
// Furthermore.
temp-> next = last;
come back last;
}
// Dynamic creation of a node.
struct Node * temp
= (struct Node *) malloc (sizeof (struct Node));
// Assign the data.
temp-> data = data;
// Adjust the links.
temp-> next = last-> next;
last-> next = temp;
come back last;
}
106
}
/ * Controller program to test the above functions * /
main integer ()
{
/ * Initialize lists as empty * /
Node * head = NULL;
head = thrust (head, 12);
head = thrust (head, 56);
head = thrust (head, 2);
head = thrust (head, 11);
cout << countNodes (head);
returns 0;
}
Production:
4
3) Reverse a circular linked list
Given a linked circular of size n. The problem is to reverse the given
circular linked list by changing the links between nodes.
Examples:
ENTRANCE:
PRODUCTION:
107
Program:
#include <bit / stdc ++. h>
using the std namespace;
108
Node * prev = NULL;
Current * node = * head_ref;
Next node *;
do {
next = current-> next;
current-> next = previous;
previous = current;
current = next;
} while (current! = (* head_ref));
109
main integer ()
{
// Create a circular linked list
// 1-> 2-> 3-> 4-> 1
Node * head = getNode (1);
head-> next = getNode (2);
head-> next-> next = getNode (3);
head-> next-> next-> next = getNode (4);
head-> next-> next-> next-> next = head;
cout << "Given list of linked circulars:";
printList (head);
reverse (and head);
cout << "\ nInverted circular linked list:";
printList (head);
returns 0;
}
Production:
Given the linked circular list: 1 2 3 4
Inverted circular linked list: 4 3 2 1
Question:
1. What differentiates a circular linked list from a normal linked list?
a) You cannot have the ‘next’ pointer point to null in a circular linked
list
b) It is faster to traverse the circular linked list
c) You may or may not have the ‘next’ pointer point to null in a
circular linked list
d) Head node is known in circular linked list
110
2. Which of the following application makes use of a circular linked list?
a) Undo operation in a text editor
b) Recursive function calls
c) Allocating CPU to resources
d) Implement Hash Tables
111
Program
Important points to remember
● In a double-linked list, the first node must always point towards the
head.
● The previous field of the first node must always be NULL.
● The next field of the last node must always be NULL.
112
Enter to the end of the list
We can use the following steps to insert a new node at the end of the
double-linked list ...
Step 1: Create a newNode with the specified value and newNode → next
as NULL.
Step 2: Check if the list is empty (head == NULL)
Step 3: If empty, set NULL to newNode → previous and newNode to
header.
Step 4: If it is not empty, define a node pointer temperature and initialize
with head.
Step 5: Keep moving the temperature to the next node until it reaches the
last node in the list (until temp → next equals NULL).
Step 6: Assign newNode to temp → next and temp to newNode →
previous.
Insert in a specific position in the list (after a node)
We can use the following steps to insert a new node after a node in the
double-bound list ...
Step 1: Create a new node with a certain value.
Step 2: Check if the list is empty (head == NULL)
Step 3: If empty, set NULL to newNode → previous and newNode →
next and set newNode as header.
Step 4: If it is not empty, define two pointers to node temp1 and temp2
and initialize temp1 with head.
Step 5: keep moving temp1 to your next node until you reach the node
after which we want to insert the newNode (as long as temp1 → data is
equal to the position, here the position is the value of the node after which
we want to insert the newNode ).
Step 6: Check every time that temp1 has been reached on the last node. If
the last node is reached, 'The specified node is not in the list! Insertion not
possible !!! 'and terminate the function. Otherwise, move temp1 to the
next node.
Step 7: Assign temp1 → next to temp2, newNode to temp1 → next, temp1
to newNode → previous, temp2 to newNode → next and newNode to
temp2 → previous.
113
deletion
In a list of double bonds, the delete operation can be performed in three
ways as follows ...
● Delete from the top of the list
● Remove from the end of the list
● Delete a specific node
116
{
case 1: printf ("Insert the value to insert:");
scanf ("% d", & value);
while (1)
{
printf ("\ nSelect from the following insert options \ n");
printf ("1. At the beginning \ n2. At the end \ n3. After a node \ n4. Cancel
\ nEnter your choice:");
scanf ("% d", & choice2);
switch (option 2)
{
case 1: insertAtBeginning (value);
break time;
case 2: insertAtEnd (value);
break time;
case 3: printf ("Enter the position after which you want to insert:");
scanf ("% d", & location);
insertAfter (value, position);
break time;
case 4: go to EndSwitch;
default: printf ("\ nSelect the correct insert option! \ n");
}
}
case 2: while (1)
{
printf ("\ nSelect from the following delete options \ n");
printf ("1. At the beginning \ n2. At the end \ n3. Specific node \ n4.
Cancel \ nEnter your choice:");
scanf ("% d", & choice2);
switch (option 2)
{
117
case 1: deleteBeginning ();
break time;
case 2: deleteEnd ();
break time;
case 3: printf ("Enter the value of the node to be removed:");
scanf ("% d", & location);
deleteSpecic (location);
break time;
case 4: go to EndSwitch;
default: printf ("\ nSelect the correct delete option! \ n");
}
}
Limit switch: pause;
case 3: display ();
break time;
case 4: exit (0);
default: printf ("\ nSelect the correct option!");
}}}
void insertAtBeginning (int value)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
newNode -> previous = NULL;
yes (head == NULL)
{
newNode -> next = NULL;
head = newNode;
}
the rest
118
{
newNode -> next = head;
head = newNode;
}
printf ("\ nThe entry was successful!");
}
void insertAtEnd (int value)
{
struct Node * newNode;
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
newNode -> next = NULL;
yes (head == NULL)
{
newNode -> previous = NULL;
head = newNode;
}
the rest
{
struct Node * temp = head;
while (temp -> next! = NULL)
temp = temp -> next;
temp -> next = newNode;
newNode -> previous = temp;
}
printf ("\ nThe entry was successful!");
}
void insertAfter (int value, int location)
{
struct Node * newNode;
119
newNode = (struct Node *) malloc (sizeof (struct Node));
newNode -> data = value;
yes (head == NULL)
{
newNode -> previous = newNode -> next = NULL;
head = newNode;
}
the rest
{
struct Node * temp1 = head, temp2;
while (temp1 -> data! = position)
{
yes (temp1 -> next == NULL)
{
printf ("The indicated node is not in the list !!!");
go to EndFunction;
}
the rest
{
temp1 = temp1 -> next;
}}
temp2 = temp1 -> next;
temp1 -> next = newNode;
newNode -> previous = temp1;
newNode -> next = temp2;
temp2 -> previous = newNode;
printf ("\ nThe entry was successful!");
}
Final function:
}
120
void deleteBeginning ()
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp = head;
yes (temp -> previous == temp -> next)
{
head = NULL;
free (temperature);
}
the rest{
head = temp -> next;
head -> front = NULL;
free (temperature);
}
printf ("\ n Deletion successful !!!");
}}
void deleteEnd ()
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp = head;
yes (temp -> previous == temp -> next)
{
head = NULL;
free (temperature);
121
}
the rest{
while (temp -> next! = NULL)
temp = temp -> next;
temp -> previous -> next = NULL;
free (temperature);
}
printf ("\ n Deletion successful !!!");
}}
void deleteSpecific (int delValue)
{
yes (head == NULL)
printf ("The list is empty! Could not delete it!");
the rest
{
struct Node * temp = head;
while (temp -> data! = delValue)
{
yes (temp -> next == NULL)
{
printf ("\ nThe indicated node is not in the list !!!");
go to FineFunction;
}
the rest
{
temp = temp -> next;
}
}
yes (temp == head)
{
122
head = NULL;
free (temperature);
}
the rest
{
temp -> previous -> next = temp -> next;
free (temperature);
}
printf ("\ n Deletion successful !!!");
}
End function:
}
blank screen ()
{
yes (head == NULL)
printf ("\ nList is empty !!!");
the rest
{
struct Node * temp = head;
printf ("\ nThe elements of the list are: \ n");
printf ("NULL <---");
while (temp -> next! = NULL)
{
printf ("% d <===>", temp -> data);
}
printf ("% d ---> NULL", temp -> data);
}}
123
Production
124
void push_back (int newElement) {
Node * newNode = new Node ();
newNode-> data = newElement;
newNode-> next = NULL;
newNode-> prev = NULL;
if (head == NULL) {
head = newNode;
} the rest {
Node * temp = head;
while (temp-> next! = NULL)
temp = temp-> next;
temp-> next = newNode;
newNode-> prev = temp;
}
}
// count the nodes in the list
int countNodes () {
Node * temp = head;
int i = 0;
while (temp! = NULL) {
i ++;
temp = temp-> next;
}
I return;
}
// show the contents of the list
void PrintList () {
Node * temp = head;
if (temp! = NULL) {
cout << "The list contains:";
125
while (temp! = NULL) {
cout <<temp-> data << "";
temp = temp-> next;
}
cout << endl;
} the rest {
cout << "The list is empty. \ n";
}}};
// test the code
int main () {
LinkedList MyList;
// Add four items to the list.
MyList.push_back (10);
MyList.push_back (20);
MyList.push_back (30);
MyList.push_back (40);
// Show the contents of the list.
MyList.PrintList ();
// number of nodes in the list
cout << "No. of nodes:" << MyList.countNodes ();
returns 0;
}
}
Production:
126
2) Find an item in a doubly linked list
Given a doubly linked list (DLL) containing N nodes and an integer X, the
task is to find the position of the entire X in the doubly linked list. If no
such position is found, print -1.
Examples:
Input: 15 <=> 16 <=> 8 <=> 7 <=> 13, X = 8
Production: 3
Explanation: X (= 8) is present at the third node of the doubly linked list.
Therefore, the required output is 3
Input: 5 <=> 3 <=> 4 <=> 2 <=> 9, X = 0
Exit: -1
Explanation: X (= 0) is not present in the doubly linked list.
Therefore, the required output is -1
Approach: Follow the steps below to fix the problem:
● Initialize a variable, say pos, to store the position of the node
that contains the X data value in the doubly linked list.
● Initializes a pointer, such as temp, to store the parent node of
the doubly linked list.
● Iterate over the linked list and for each node check if the data
value of that node equals X or not. If determined to be true,
print pos.
● Otherwise, press -1.
Program:
// Structure of a node
// the doubly linked list
node structure {
127
// Store the pointer
// to the next node
Next node *;
128
// Change the previous header
// from node to new node
(* head_ref) -> prev = new_node;
}
// Update position
position ++;
129
// Update temperature
temp = temp-> next;
}
// Driver code
main integer ()
{
Node * head = NULL;
intX = 8;
// Create the doubly linked list
// 18 <-> 15 <-> 8 <-> 9 <-> 14
push (and head, 14);
push (and head, 9);
push (and head, 8);
push (and head, 15);
push (and head, 18);
cout << search (& testa, X);
returns 0;
}
130
Production: 3
1) Reverse a doubly linked list
Given a doubly linked list, the task is to reverse the given doubly linked
list.
See the following diagrams, for example.
(a) Double linked original list
/ * Before changing the head, check that the speakers are empty
list and list with a single node * /
yes (temp! = NULL)
* head_ref = temp-> previous;
}
/ * UTILITY FUNCTIONS * /
/ * Function to insert a node in the
start of list doubly linked * /
push empty (node ** head_ref, int new_data)
{
/ * assign node * /
Node * new_node = new node ();
132
/ * since we are adding at the beginning,
prev is always NULL * /
new_node-> prev = NULL;
133
/ * We create an ordered linked list to test the functions
The created linked list will be 10-> 8-> 4-> 2 * /
press (& testa, 2);
push (and head, 4);
push (and head, 8);
push (and head, 10);
returns 0;
}
Production:
Original linked list
10 8 4 2
The inverted linked list is
2 4 8 10
134
Questions:
a) head-6-1-2-3-4-5-tail
b) head-6-1-2-3-4-tail
c) head-1-2-3-4-5-6-tail
d) head-1-2-3-4-5-tail
135
4. Objective: Add two polynomials using a linked list
Theory:
Given two polynomial numbers represented by a linked list. Writing a
function that aggregates these lists means adding the coefficients that have
the same variable powers.
Example:
Entrance:
1st number = 5x2 + 4x1 + 2x0
2nd number = -5x1 - 5x0
Production:
5x2-1x1-3x0
Entrance:
1st number = 5x3 + 4x2 + 2x0
2nd number = 5x ^ 1 - 5x ^ 0
Production:
5x3 + 4x2 + 5x1 - 3x0
136
Program:
// use linked lists
#include <bit / stdc ++. h>
using the std namespace;
138
poly1 = poly1-> next;
poly2 = poly2-> next;
}
// Controller code
main integer ()
{
struct Node * poly1 = NULL, * poly2 = NULL, * poly = NULL;
140
polyadd (poly1, poly2, poly);
returns 0;
}
Production:
1st number: 5x ^ 2 + 4x ^ 1 + 2x ^ 0
Second number: -5x ^ 1-5x ^ 0
Aggregate polynomial: 5x ^ 2-1x ^ 1-3x ^ 0
141
Module V
Objective:
Use the queues for basic time simulations. Be able to recognize the
properties of the problem where stacks, queues and deque are suitable data
structures. Being able to implement the abstract data type list as a linked
list using the reference node and model.
Theory:
142
Operation entry
The insert operation adds the queue by adding an item to the end of
the queue. The new item will be the last item in the queue.
First, allocate the memory for the new ptr node using the following
declaration.
There can be two scenarios of putting this new ptr node into the linked
queue.
In the first scenario, we put an item in an empty queue. In this case, the
front = NULL condition becomes true. Now the new element will be
added as the only element in the queue and the next front and back pointer
will point to NULL.
In the second case, the queue contains more than one element. The
front = NULL condition becomes false. In this scenario, you need to
update the final trailing pointer so that the next trailing pointer points to
the new ptr node. Since this is a linked queue, we also need to make the
back pointer point to the newly added ptr node. We also need to make the
pointer to the next end point NULL.
This puts the item in the queue. The algorithm and implementation
of C are shown below.
143
Algorithm
Step 1: Allocate space for the new PTR node
Step 2: SET PTR -> DATA = VAL
Step 3: IF FRONT = NULLSET FRONT = REAR = PTRSET FRONT ->
NEXT = REAR -> NEXT = NULLELSESET REAR -> NEXT =
PTRSET REAR = PTRSET REAR -> NEXT = NULL [END OF IF]
Step 4: FINISH
Program:
insert empty (struct node * ptr, int element;)
{
ptr = (structure node *) malloc (size of (structure node));
yes (ptr == NULL)
{
printf ("\ nOVERFLOW \ n");
come back;
}
the rest
{
ptr -> data = element;
yes (front == NULL)
{
front = ptr;
posterior = ptr;
front -> next = NULL;
rear -> next = NULL;
}
the rest
{
posterior -> next = ptr;
posterior = ptr;
144
back-> next = NULL;
}}}
deletion
● The delete operation removes the item inserted first of all items in
the queue. First of all, we need to check if the list is empty or not.
The condition front == NULL becomes true if the list is empty, in
this case we simply write underflow in the console and exit.
● Otherwise, we will remove the element that the front pointer points
to. To do this, copy the node pointed to by the front pointer to the
ptr pointer. Now, move the front pointer, point to your next node
and release the node pointed to by the ptr node. This is done using
the following statements.
ptr = in front;
front = front -> forward;
free (ptr);
Algorithm
Step 1: IF FRONT = NULL Type "Underflow" Go to step 5 [END OF IF]
Program:
remove void (structure node * ptr)
{
yes (front == NULL)
{
printf ("\ nUNDERFLOW \ n");
come back;
}
the rest
{
145
ptr = in front;
front = front -> forward;
free (ptr);
}}
Program:
#include <stdio.h>
#include <stdlib.h>
structure node
{
int data;
next structure node *;
};
front structure knot *;
knot back structure *;
blank insert ();
cancel cancel ();
blank display ();
main vacuum ()
{
int choice;
while (choice! = 4)
{
printf ("\ n ************************* Main menu
****************** ***********\North");
printf ("\ n ============================================
= =================== \ n ");
printf ("\ n1.insert an item \ n2. Delete an item \ n3. Show queue \
n4.Sexit \ n");
printf ("\ nPlease enter your choice?");
scanf ("% d", & option);
change (choice)
146
{
Case 1:
to insert();
break time;
case 2:
To remove();
break time;
case 3:
show();
break time;
case 4:
output (0);
break time;
default:
printf ("\ nPlease enter a valid choice ?? \ n");
}
}
}
blank insert ()
{
struct node * ptr;
int element;
ptr = (structure node *) malloc (size of (structure node));
yes (ptr == NULL)
{
printf ("\ nOVERFLOW \ n");
come back;
}
the rest
{
147
printf ("\ nPlease insert value? \ n");
scanf ("% d", & element);
ptr -> data = element;
yes (front == NULL)
{
front = ptr;
posterior = ptr;
front -> next = NULL;
rear -> next = NULL;
}
the rest
{
posterior -> next = ptr;
posterior = ptr;
back-> next = NULL;
}
}
}
delete delete ()
{
struct node * ptr;
yes (front == NULL)
{
printf ("\ nUNDERFLOW \ n");
come back;
}
the rest
{
ptr = in front;
front = front -> forward;
148
free (ptr);
}
}
blank screen ()
{
struct node * ptr;
ptr = in front;
yes (front == NULL)
{
printf ("\ n Empty queue \ n");
}
the rest
{printf ("\ nprint values ..... \ n");
while (ptr! = NULL)
{
printf ("\ n% d \ n", ptr -> data);
ptr = ptr -> next;
}}}
Production:
***********Main menu**********
==============================
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 1
Enter value?
123
***********Main menu**********
==============================
149
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 1
Enter value?
90
***********Main menu**********
==============================
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 3
print values .....
123
90
***********Main menu**********
==============================
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 2
***********Main menu**********
==============================
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 3
print values .....
150
90
***********Main menu**********
==============================
1.Enter a subject
2.Remove an item
3. Show the queue
4.exit
Enter your choice? 4
2. Objective: Implementation of the circular queue array
Objective:
The circular queue solves the main limitation of the normal queue.
In a normal queue, after some insertion and deletion, there will be blank,
unusable space.
Theory:
As we can see in the image above, the back is in the last position of
the queue and the front is pointing somewhere instead of position 0. In the
array above, there are only two elements and three other positions are
empty. . The rear is in the last position of the tail; if we try to insert the
element, it will show that there are no empty spaces in the queue. There is
a solution to avoid such a waste of memory space by moving both
151
elements to the left and adjusting the front and rear ends accordingly. This
is not a practically good approach because changing all the elements will
take time. The effective approach to avoiding memory waste is to use the
data structure of the circular queue.
● If rear! = Max - 1, the back will increase to mod (maxsize) and the
new value will be inserted at the end of the queue.
● Yes in front! = 0 and back = max - 1, it means the queue is not full,
so set the back value to 0 and put the new element there.
● When front == 0 && rear = max-1, it means the front is in the first
position of the tail and the back is in the last position of the tail.
● front == rear + 1;
Algorithm:
● First, let's check if the queue is empty or not. If the queue is empty,
we cannot perform the queue cancel operation.
● When the element is removed, the front value is reduced by 1.
● If there is only one element left that needs to be removed, the front
and back are reset to -1.
Algorithm:
Step 1: IF FRONT = -1
Enter "UNDERFLOW"
Go to step 4
[END of S]
Step 2: SET VAL = QUEUE [FRONT]
Step 3: IF FRONT = REAR
SET FRONT = REAR = -1
THE REST
IF FRONT = MAX -1
FRONT SET = 0
THE REST
SET FRONT = FRONT + 1
[END of S]
[END OF S]
Step 4: EXIT
154
155
Program:
Program:
#include <stdio.h>
# define maximum 6
156
int queue [max]; // declaration of the array
front int = -1;
back int = -1;
// function to put an item in a circular queue
empty queuing (int element)
{
if (front == - 1 && rear == - 1) // condition to verify that the queue is
empty
{
front = 0;
rear = 0;
tail [back] = element;
}
else if ((rear + 1)% max == front) // condition to check that the queue is
full
{
printf ("The queue is overflowing ..");
}
the rest
{
rear = (rear + 1)% max; // the rear is increased
tail [back] = element; // assign a value to the rearmost queue.
}}
// function to remove the item from the queue
int dequeue ()
{
if ((front == - 1) && (rear == - 1)) // condition to verify that the queue is
empty
{
printf ("\ nQueue is underflow ..");
}
157
else if (front == rear)
{
printf ("\ nThe removed item from the queue is% d", queue [front]);
front = -1;
rear = -1;
}
the rest
{
printf ("\ nThe removed item from the queue is% d", queue [front]);
front = (front + 1)% max;
}}
// function to display the elements of a queue
blank screen ()
{
int i = front;
yes (front == - 1 && rear == - 1)
{
printf ("\ n The queue is empty ..");
}
the rest
{
printf ("\ nThe elements of a queue are:");
while (i <= behind)
{
printf ("% d,", tail [i]);
i = (i + 1)% maximum;
}}}
main integer ()
{
int choice = 1, x; // declaration of variables
158
while (option <4 && option! = 0) // while loop
{
printf ("\ n Press 1: Insert an element");
printf ("\ nPress 2: Delete an item");
printf ("\ nPress 3: Show item");
printf ("\ nPlease enter your choice");
scanf ("% d", & option);
change (choice)
{
Case 1:
printf ("Insert the element to insert");
scanf ("% d", & x);
tail (x);
break time;
case 2:
dequeue ();
break time;
case 3:
show();
}}
returns 0;
}
159
Production:
Questions:
Objective:
The priority queue (also known as a stripe) is used to keep track of
unexplored paths, where a lower bound on the total path length is lower
and has the highest priority.
Theory:
The queue is a FIFO data structure where the element that is
inserted first is the first to be removed. A priority queue is a type of queue
in which items can be inserted or removed based on priority. It can be
implemented using a linked queue, stack, or list data structure. The
priority queue is implemented following these rules:
● The data or items with the highest priority will run before the data
or items with the lowest priority.
● If two items have the same priority, they will be executed in the
sequence in which they are added to the list.
A node in a linked list to implement the priority queue will contain three
parts:
● Data: will store the integer value.
● Address: will store the address of a subsequent node
● Priority: will store the priority, which is an integer value. It can
range from 0 to 10, where 0 represents the highest priority and 10
represents the lowest priority.
161
Example
Entrance
Production
Algorithm:
Start
Step 1-> Declare a tree node
Declare data, priority
Declare a structure node * below
Step 2-> In the Node function * newNode (int d, int p)
Set Node * temp = (Node *) malloc (size of (Node))
Set temp-> data = d
Set temp-> priority = p
Set temperature-> next = NULL
Return temperature
Step 3-> In the int peek function (Node ** head)
return (* head) -> data
Step 4-> In the pop void function (Node ** head)
Set node * temp = * head
Set (* head) = (* head) -> next
free (temporary)
Step 5-> In the push function (Node ** head, int d, int p)
Set node * start = (* head)
Set Node * temp = new Node (d, p)
162
If (* head) -> priority> p then,
Set temperature-> next = * head
Set (* head) = temp
The rest
Loop While start-> next! = NULL && start-> next-> priority <p
Set start = start-> next
Set temperature-> next = start-> next
Set start-> next = temperature
Step 6-> In the int isEmpty (Node ** head) function
Return (* head) == NULL
Step 7-> In the int main () function
Set node * pq = newNode (7, 1)
Push call function (& pq, 1, 2)
Push call function (& pq, 3, 3)
Push function call (& pq, 2, 0)
While loop (! IsEmpty (& pq))
Print the results obtained by peek (& pq)
Call function pop (& pq)
To stop
Program:
#include <stdio.h>
#include <stdlib.h>
// priority node
typedef struct node {
int data;
int priority;
next structure node *;
} Node;
Node * newNode (int d, int p) {
Node * temp = (Node *) malloc (size of (Node));
163
temp-> data = d;
temp-> priority = p;
temp-> next = NULL;
return temperature;
}
int peek (knot ** head) {
return (* header) -> data;
}
empty pop (knot ** head) {
Node * temp = * head;
(* head) = (* head) -> next;
free (temperature);
}
push empty (node ** head, int d, int p) {
Knot * start = (* head);
Node * temp = newNode (d, p);
if ((* head) -> priority> p) {
temp-> next = * head;
(* head) = temperature;
} the rest {
while (start-> next! = NULL &&
start-> next-> priority <p) {
start = start-> next;
}
// Or at the end of the list
// or in the requested location
temp-> next = start-> next;
start-> next = temp;
}
}
164
// Function to verify that the queue is empty
int isEmpty (node ** head) {
return (* head) == NULL;
}
// main function
int main () {
Node * pq = newNode (7, 1);
press (& pq, 1, 2);
press (& pq, 3, 3);
press (& pq, 2, 0);
while (! isEmpty (& pq)) {
printf ("% d", see (& pq));
pop (& pq);
}
returns 0;
}
Production
2713
Questions:
1. With what data structure can a priority queue be implemented?
a) Array
b) List
c) Heap
d) Tree
2. Which of the following is not an application of priority queue?
a) Huffman codes
b) Interrupt handling in operating system
c) Undo operation in text editors
d) Bayesian spam filter
165
3. What is not a disadvantage of priority scheduling in operating
systems?
a) A low priority process might have to wait indefinitely for the CPU
b) If the system crashes, the low priority systems may be lost
permanently
c) Interrupt handling
d) Indefinite blocking
4. Which of the following is not an advantage of a priority queue?
a) Easy to implement
b) Processes with different priority can be efficiently handled
c) Applications with differing requirements
d) Easy to delete elements in any case
4. Objective: Implement double-ended queuing in C / C ++
Objective:
Double Ended Queue is also a queue data structure where insert
and delete operations are performed on both ends (front and back). This
means that we can insert both in the front and back position and we can
remove in both the front and back position.
Theory:
Dequeue stands for Double Ended Tail. In the tail, the insertion
takes place from one end while the removal from the other end. The end
where the insertion takes place is known as the posterior end, while the
end where the removal takes place is known as the anterior end.
166
Then the insert and delete operation can be performed from the side.
The stack follows the LIFO rule in which both insertion and removal can
be done from one end; therefore, we conclude that deque can be
considered as a stack.
Then the insertion can be done from one end and the removal can
be done from the other end. The queue follows the FIFO rule where the
element is inserted on one side and removed on the other. Therefore, we
conclude that the deque can also be regarded as the tail.
There are two types of queues, restricted entry queue and restricted
exit queue.
Operations in Deque
● isFull (): this function returns true if the stack is full; otherwise, it
returns a false value.
● isEmpty (): this function returns true if the stack is empty;
otherwise, it returns a false value.
Memory representation
Queued operation
168
2. Since the deque is empty, inserting an element from the front or
back would be the same. Suppose we entered element 1, so front is
equal to 0 and back is also equal to 0.
169
Tail pull operation
1. If the front points to the last element of the array and we want to
perform the delete operation from the front. To remove any
elements from the front, we must set front = front + 1. Currently
the value of the front is equal to 4, and if we increase the value of
the front, it becomes 5, which is not a valid index. So we conclude
that if front points to the last element, then front is set to 0 in case
of a delete operation.
3. If the back points to the first element and we want to remove the
element from the back, then we need to set rear = n-1 where n is
the size of the array as shown in the figure below:
170
Let's create a deque program.
The following are the six functions we used in the following program:
Program:
#defined size 5
#include <stdio.h>
int deque [size];
int f = -1, r = -1;
// the enqueue_front function will insert the value from the front
void enqueue_front (int x)
{
if ((f == 0 && r == size-1) || (f == r + 1))
{
printf ("what is full");
}
plus if ((f == - 1) && (r == - 1))
{
171
f = r = 0;
deque [f] = x;
}
yes no (f == 0)
{
f = dimension-1;
deque [f] = x;
}
the rest
{
f = f-1;
deque [f] = x;
}}
// the enqueue_rear function will insert the value from behind
void enqueue_rear (int x)
{
if ((f == 0 && r == size-1) || (f == r + 1))
{
printf ("what is full");
}
plus if ((f == - 1) && (r == - 1))
{
r = 0;
deque [r] = x;
}
plus if (r == size-1)
{
r = 0;
deque [r] = x;
}
the rest
{
r ++;
deque [r] = x;
172
}}
// the display function prints the entire value of deque.
blank screen ()
{
int i = f;
printf ("\ n Elements in a deque:");
while (i! = r)
{
printf ("% d", deque [i]);
i = (i + 1)% of the dimension;
}
printf ("% d", deque [r]);
}
// The getfront function retrieves the first value of the deque.
empty getfront ()
{
if ((f == - 1) && (r == - 1))
{
printf ("What is empty");
}
the rest
{
printf ("\ nThe value of the front is:% d", deque [f]);
}}
// The getrear function retrieves the last value of the deque.
getrear empty ()
{
if ((f == - 1) && (r == - 1))
{
printf ("What is empty");
}
the rest
{
printf ("\ nThe bottom value is:% d", deque [r]);
173
}}
// The dequeue_front () function removes the element from the front
empty dequeue_front ()
{
if ((f == - 1) && (r == - 1))
{
printf ("What is empty");
}
if not (f == r)
{
printf ("\ nThe deleted item is% d", deque [f]);
f = -1;
r = -1;
}
plus if (f == (size-1))
{
printf ("\ nThe deleted item is% d", deque [f]);
f = 0;
}
the rest
{
printf ("\ nThe deleted item is% d", deque [f]);
f = f + 1;
}}
// the dequeue_rear () function removes the element from the back
dequeue_rear empty ()
{
if ((f == - 1) && (r == - 1))
{
printf ("What is empty");
}
if not (f == r)
{
printf ("\ nThe deleted item is% d", deque [r]);
174
f = -1;
r = -1;
}
if not (r == 0)
{
printf ("\ nThe deleted item is% d", deque [r]);
r = dimension-1;
}
the rest
{
printf ("\ nThe deleted item is% d", deque [r]);
r = r-1;
}}
main integer ()
{
// entering a value from the front.
enqueue_front (2);
// entering a value from the front.
enqueue_front (1);
// entering a value from behind.
rear_tail (3);
// entering a value from behind.
enqueue_rear (5);
// entering a value from behind.
enqueue_rear (8);
// Call the view function to retrieve the deque values
show();
// Get the front value front
getfront ();
// Get the return value.
getrear ();
// remove a foreground value
dequeue_front ();
// clear a value from the back
175
dequeue_rear ();
// Call the view function to retrieve the deque values
show();
returns 0;
}
Production:
Question:
1. What is a dequeue?
a) A queue with insert/delete defined for both front and rear ends of the queue
b) A queue implemented with a doubly linked list
c) A queue implemented with both singly and doubly linked lists
d) A queue with insert/delete defined for front side of the queue
3. What is the time complexity of deleting from the rear end of the dequeue
implemented with a singly linked list?
a) O(nlogn)
b) O(logn)
c) O(n)
d) O(n2)
176
Module VI (Tree)
Experiment No-1
Aim:
Creating Binary search tree.
Objective:
Writing C++ program to create binary search tree.
Theory:
A binary tree is a special type of tree that can only have up to two
children. This means that a particular node in a binary tree can have no
child, one child, or two children but not more. A Binary search tree is a
type of binary tree.
The left subtree of a root node contains value lesser than the root
node’s value.
The right subtree of a root node contains value greater than the
root node’s value.
The left and right subtree of the root node each must also be a
binary search tree.
177
can be any number of leaf nodes present in a general tree. Leaf nodes can
also be called external nodes.
Internal nodes: A node that has atleast one child node is known as an
internal node.
Ancestor node: An ancestor of a node is any predecessor node on a path
from the root to that node.
Descendant: The immediate successor of the given node is known as a
descendant of a node.
ROOT
11
Left Sub Tree Right Sub Tree
6 19
4 9 22
Algorithm:
Inserting node in BST
1. Allocate the memory for tree.
2. Set the data part to the value and set the left and right pointer of
tree, point to NULL.
3. If the item to be inserted is the first element of the tree, then the
left and right of this node will point to NULL.
4. Else, check whether the item is less than the root element of the
tree, if this is true, then recursively perform this operation with the
left sub tree of the root.
5. If this is false, then perform this operation recursively with the
right sub-tree of the root.
178
Program:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
void insert(int);
struct node
{
int data;
struct node *left;
struct node *right;
};
struct node *root;
int main ()
{
int choice,item;
do
{
cout<<"\nEnter the item which you want to insert?\n";
cin>>item;
insert(item);
cout<<"\n Press 0 to insert more? \n";
cin>>choice;
}while(choice == 0);
return 0;
}
void insert(int item)
{
struct node *ptr, *parentptr , *nodeptr;
ptr = (struct node *) malloc(sizeof (struct node));
if(ptr == NULL)
{
179
cout<<"cannot insert";
}
else
{
ptr -> data = item;
ptr -> left = NULL;
ptr -> right = NULL;
if(root == NULL)
{
root = ptr;
root -> left = NULL;
root -> right = NULL;
}
else
{
parentptr = NULL;
nodeptr = root;
while(nodeptr != NULL)
{
parentptr = nodeptr;
if(item < nodeptr->data)
{
nodeptr = nodeptr -> left;
}
else
{
nodeptr = nodeptr -> right;
}
}
if(item < parentptr -> data)
{
parentptr -> left = ptr;
180
}
else
{
parentptr -> right = ptr;
}
}
cout<<"Node Inserted";
}
OUTPUT:
Question:
1) The following numbers are inserted into an empty binary search
tree in the given order: 10, 1, 3, 5, 15, 12, 16. What is the height of
the binary search tree (the height is the maximum distance of a leaf
node from the root)?
A. 2
B. 3
C. 5
D. 4
181
2) Construct a Binary search tree by inserting the following numbers
from left to right:
11,6,8,19,4,10,5,18,43,49,31
3) A binary search tree is generated by inserting in order the
following integers:
50, 15, 62, 5, 20, 58, 91, 3, 8, 37, 60, 24
The number of nodes in the left subtree and right subtree of the
root respectively is
A. (4, 7)
B. (7, 4)
C. (8, 3)
D. (3, 8)
Experiment No2
Aim:
Traversal of Binary Search Tree
Objective:
Writing c++ program to traverse through the Binary Search tree
using all the three method.
Theory:
Traversal refers to the process of visiting each node in a tree
(binary search tree). Because, all nodes are connected via edges (links),
traversing always start from the root (head) node. That is, we cannot
randomly access a node in a tree. There are three ways in which we can
traverse a binary search tree −
1) In-order Traversal
2) Pre-order Traversal
3) Post-order Traversal
182
Example:
Root
16
10 20
8 12 17 24
Fig:2.1
183
3) Post-Order Traversal (Left-Right-Root)
In this traversal method, the root node is visited last, hence it is
called as Post Order Traversal. First, we traverse the left subtree, then the
right subtree and finally the root node.
Consider the fig 2.1, if this binary search tree is traversed using
Post-Order Traversal method, then the node traverse will be in the
following order: -
8-12-10-17-24-20-16
We start from 16, and following post-order traversal, we first visit
the left subtree 10. 10 is also traversed post-order. The process goes on
until all the nodes are visited.
Algorithm:
Inorder(tree)
1. Traverse the left subtree, i.e., call Inorder(left-subtree)
2. Visit the root.
3. Traverse the right subtree, i.e., call Inorder(right-subtree)
Preorder (tree)
1. Visit the root.
2. Traverse the left subtree, i.e., call Preorder(left-subtree)
3. Traverse the right subtree, i.e., call Preorder(right-subtree)
Postorder(tree)
1. Traverse the left subtree, i.e., call Postorder(left-subtree)
2. Traverse the right subtree, i.e., call Postorder(right-subtree)
3. Visit the root.
Program:
# include <iostream>
# include <cstdlib>
using namespace std;
187
insert(tree->left, newnode);
}
else
{
tree->left = newnode;
(tree->left)->left = NULL;
(tree->left)->right = NULL;
cout<<"Node Added To Left"<<endl;
return;
}
}
else
{
if (tree->right != NULL)
{
insert(tree->right, newnode);
}
else
{
tree->right = newnode;
(tree->right)->left = NULL;
(tree->right)->right = NULL;
cout<<"Node Added To Right"<<endl;
return;
}
}
}
188
{
cout<<"Tree is empty"<<endl;
return;
}
if (ptr != NULL)
{
cout<<ptr->info<<" ";
preorder(ptr->left);
preorder(ptr->right);
}
}
// In Order Traversal
void BST::inorder(node *ptr)
{
if (root == NULL)
{
cout<<"Tree is empty"<<endl;
return;
}
if (ptr != NULL)
{
inorder(ptr->left);
cout<<ptr->info<<" ";
inorder(ptr->right);
}
}
// Postorder Traversal
void BST::postorder(node *ptr)
{
if (root == NULL)
189
{
cout<<"Tree is empty"<<endl;
return;
}
if (ptr != NULL)
{
postorder(ptr->left);
postorder(ptr->right);
cout<<ptr->info<<" ";
}
}
190
Output:
191
Question:
1) What is the specialty about the in-order traversal of a binary search
tree?
a) It traverses in a non-increasing order
b) It traverses in an increasing order
c) It traverses in a random fashion
d) It traverses based on priority of the node
11
10 12
5 3 4
a)
192
10
4 11
5 3 12
b)
10
4 11
3 5 12
c)
12
10 11
5 3 4
d)
Experiment No:3
Aim:
Finding Maximum and Minimum Node of the binary search tree.
Objective:
Writing c++ program to find maximum and minimum node of the binary
search tree.
Theory:
As in the binary search tree, nodes less than root node goes to the
left and nodes greater than root node goes to the right. So, in Binary
Search Tree, we can find maximum node by traversing right pointers until
193
we reach the rightmost node. Similarly, we can find minimum node by
traversing left pointer until we reach the leftmost node.
For example, consider the following Binary Search Tree,
Root
14
10 20
8 12 18 30
194
# include <cstdlib>
struct node
{
int key;
struct node *left, *right;
};
int main()
{
int maxValue(struct node* );
struct node* insert(struct node* , int );
int minValue(struct node* );
struct node *root = NULL;
root = insert(root, 8);
insert(root, 3);
insert(root, 10);
insert(root, 1);
insert(root, 6);
insert(root, 4);
insert(root, 7);
insert(root, 5);
insert(root, 10);
insert(root, 9);
insert(root, 13);
insert(root, 11);
196
insert(root, 18);
insert(root, 12);
insert(root, 2);
Question:
1) What will be the minimum element of the binary search tree if no
left subtree exist?
2) Which of the following is false about a binary search tree?
a) The left child is always lesser than its parent
b) The right child is always greater than its parent
c) The left and right sub-trees should also be binary search trees
d) In order sequence gives decreasing order of elements
3) What are the worst case and average case complexities of a binary
search tree?
a) O(n), O(n)
b) O(logn), O(logn)
c) O(logn), O(n)
d) O(n), O(logn)
197
Experiment:4
Aim:
Counting number of nodes in binary search tree.
Objectives:
Writing c++ program to count number of nodes in the binary
search tree.
Theory:
To count number of nodes in the binary search tree we can use the
following formula: -
Total No. of nodes in BST=Total No. of nodes in left sub-tree +
Total no. of node in right sub-tree + 1
ROOT
25
Left Sub Tree Right Sub Tree
16 39
14 17 40
Algorithm:
1. Initialize “count” variable as 1.
2. If root is NULL, return 0.
3. Else, count = count + countNodes(root -> left) and
count = count + countNodes(root -> right).
4. Then, return count.
5. End If
198
Program:
#include<iostream>
using namespace std;
int n=1;
struct node
{
int data;
node* left;
node* right;
};
return root;
}
int CountNodes(node*root)
{
if(root==NULL)
return 0;
if(root->left!=NULL)
{
n=n+1;
199
n=CountNodes(root->left);
}
if(root->right!=NULL)
{
n=n+1;
n=CountNodes(root->right);
}
return n;
}
int main()
{
node* root=NULL;
root=Insert(root,3);
Insert(root,4);
Insert(root,2);
Insert(root,5);
Insert(root,1);
Insert(root,6);
Insert(root,8);
return 0;
}
Output:
200
Questions:
1) What are sub trees in binary search tree?
2) How to calculate height of the binary search tree?
3) What are the various application of binary search tree?
Experiment No-5
Aim:
Creating Max Heap
Objective:
Writing c++ program to create max heap data structure.
Theory:
Heap: A Heap is a special Tree-based data structure in which the tree is a
complete binary tree, that is, each level of the tree is completely filled,
except possibly the bottom level. At this level, it is filled from left to right.
Generally, Heaps can be of two types:
Max-Heap: In a Max-Heap the key present at the root node must be
greatest among the keys present at all of it’s children. The same property
must be recursively true for all sub-trees in that Binary Tree.
Min-Heap: In a Min-Heap the key present at the root node must be
minimum among the keys present at all of it’s children. The same property
must be recursively true for all sub-trees in that Binary Tree.
Note: Heap data Structure is implemented using Arrays in
Programming Languages.
Example of Max-Heap
ROOT
99
40 50
10 15 50 40
MaxHeap
201
In the above figure , 99 is the root node and it is the highest node
in the tree.In left sub tree 40 is parent of 10 and 15, which is again
greater.In right sub tree 50 is the parent of 50 and 40,which is also greater.
99 40 50 10 15 50 40
Index 1 2 3 4 5 6
0
Array Representation of the above max-heap:
Note: In Heap data structure two nodes can have same value, that is
repetition of the value is allowed in heap data structure.
Algorithm:
1. Create a new node at the end of heap.
2. Assign new value to the node.
3. Compare the value of this child node with its parent.
4. If value of parent is less than child, then swap them.
5. Repeat step 3 & 4 until Heap property holds (i.e. parent >= child).
Program:
#include <iostream>
using namespace std;
void max_heap(int *a, int m, int n) {
int j, t;
t = a[m];
j = 2 * m;
while (j <= n) {
if (j < n && a[j+1] > a[j])
j = j + 1;
if (t > a[j])
break;
else if (t <= a[j]) {
a[j / 2] = a[j];
j = 2 * j;
}
}
a[j/2] = t;
return;
}
void build_maxheap(int *a,int n) {
int k;
for(k = n/2; k >= 1; k--) {
202
max_heap(a,k,n);
}
}
int main() {
int n, i;
cout<<"enter no of elements of array\n";
cin>>n;
int a[30];
for (i = 1; i <= n; i++) {
cout<<"enter elements"<<" "<<(i)<<endl;
cin>>a[i];
}
build_maxheap(a,n);
cout<<"Max Heap\n";
for (i = 1; i <= n; i++) {
cout<<a[i]<<endl;
}
}
Output:
203
Questions:
1. Consider a binary max-heap implemented using an array. Which
one of the following arrays represents a binary max-heap? (GATE
CS 2009)
a) 25,12,16,13,10,8,14
b) 25,12,16,13,10,8,14
c) 25,14,16,13,10,8,12
d) 25,14,12,13,10,8,16
2. When do you need to use a heap?
3. Construct a max heap using [12,10,9,8,5,2].
Experiment No-6
Aim: Creating Min Heap
Objective:
Writing c++ program to create min heap data structure.
Theory:
Heap: A Heap is a special Tree-based data structure in which the tree is a
complete binary tree, that is, each level of the tree is completely filled,
except possibly the bottom level. At this level, it is filled from left to right.
Generally, Heaps can be of two types:
Max-Heap: In a Max-Heap the key present at the root node must be
greatest among the keys present at all of it’s children. The same property
must be recursively true for all sub-trees in that Binary Tree.
Min-Heap: In a Min-Heap the key present at the root node must be
minimum among the keys present at all of it’s children. The same property
must be recursively true for all sub-trees in that Binary Tree.
Example of Min-Heap
ROOT
10
14 15
25 30 42 27
44 35 33
MinHeap
204
In the above figure, 10 is the root node and it is the smallest node in the
tree. Same is true for every sub node.In min heap,the value of the root
node is less than or equal to either of its children.
Array Representation of the above min-heap:
10 14 15 25 30 42 27 44 35 33
Index 1 2 3 4 5 6 7 8 9
0
Note: In Heap data structure two nodes can have same value, that is
repetition of the value is allowed in heap data structure.
Algorithm:
1. Create a new node at the end of heap.
2. Assign new value to the node.
3. Compare the value of this child node with its parent.
4. If value of parent is greater than child, then swap them.
5. Repeat step 3 & 4 until Heap property holds(i.e parent <= child).
Program:
#include <iostream>
#include <conio.h>
using namespace std;
void min_heap(int *a, int m, int n){
int j, t;
t= a[m];
j = 2 * m;
while (j <= n) {
if (j < n && a[j+1] < a[j])
j = j + 1;
if (t < a[j])
break;
else if (t >= a[j]) {
a[j/2] = a[j];
j = 2 * j;
}
}
a[j/2] = t;
return;
}
void build_minheap(int *a, int n) {
205
int k;
for(k = n/2; k >= 1; k--) {
min_heap(a,k,n);
}
}
int main() {
int n, i;
cout<<"enter no of elements of array\n";
cin>>n;
int a[30];
for (i = 1; i <= n; i++) {
cout<<"enter element"<<" "<<(i)<<endl;
cin>>a[i];
}
build_minheap(a, n);
cout<<"Min Heap\n";
for (i = 1; i <= n; i++) {
cout<<a[i]<<endl;
}
getch();
}
Output:
206
Questions:
1. In a min-heap, element with the lowest key is always in which
node?
a) Leaf node
b) Root node
c) First node of left sub tree
d) First node of right sub tree
Experiment No:7
Aim:
Performing Reheap Up operation on max-Heap and min Heap.
Objective:
Writing c++ program to perform reheap operation i.e insert new
element in the Heap.
Theory:
Reheap Up is used when inserting new element in the heap.
Whenever new element is added in the heap it is always added to the first
empty leaf at the bottom level from the leftmost side. After that heap is
rearranged so that newly added element reached its proper place. For max
heap swapping is done, if new value is greater than previous/parent node.
For min heap swapping is done, if new value is smaller than
previous/parent node.
207
Suppose the Heap is a Max-Heap as shown below:
ROOT
8
5 3
2 4
ROOT
8
5 3
2 4 15
ROOT
8
5 15
2 4 3
208
15 is again more than its parent 8, swap them.
ROOT
15
5 8
2 4 3
ROOT
15
5 8
2 4 3
209
Program:
C++ program to insert new element in Max-Heap:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,i,m; //n is no of elements,i is normal integer and m is used to
not change n
cout<<"How Much Elements are in Your Heap: ";
cin>>n;
cout<<"Before Insertion:"<<endl;
for(i=1;i<=n;i++){
cout<<H[i]<<" ";
}
cout<<endl<<endl;
210
cout<<"After Insertion:"<<endl;
for(i=1;i<=n;i++){
cout<<H[i]<<" ";
}
cout<<endl;
return 0;
}
Output:
int main(){
int n,i,m; //n is no of elements,i is normal integer and m is used to
not change n
cout<<"How Much Elements are in Your Heap: ";
cin>>n;
211
cout<<"Enter All Elements of Min-Heap in Sequential
Representation:"<<endl;
for(i=1;i<=n;i++){
cin>>H[i];
}
cout<<endl;
cout<<"Before Insertion:"<<endl;
for(i=1;i<=n;i++){
cout<<H[i]<<" ";
}
cout<<endl<<endl;
cout<<"After Insertion:"<<endl;
for(i=1;i<=n;i++){
cout<<H[i]<<" ";
}
cout<<endl;
return 0;
}
212
Output:
Question:
1. What is the correct way of adding new element to the heap?
2. Explain reheap up process in detail?
3. What is mean by Heapify?
Experiment No:8
Aim:
Performing Reheap down operation on max-Heap and min Heap.
Objective:
Writing c++ program to perform reheap down i.e deletion of
element from the Heap.
Theory:
Reheap down is used when deleting an element from the heap. The
standard deletion operation on Heap is to delete the element present at the
root node of the Heap. That is if it is a Max Heap, the standard deletion
operation will delete the maximum element and if it is a Min heap, it will
delete the minimum element.
Since deleting an element at any intermediary position in the heap
can be costly, so we can simply replace the element to be deleted by the
last element and delete the last element of the Heap.
213
Suppose the Heap is a Max-Heap as:
ROOT
20
18 19
15 13
Step 1: Replace the last element with root, and delete it.
ROOT
13
18 19
15 20
ROOT
13
18 19
15
214
Step 2: Heapify root.
Final Heap:
ROOT
19
18 13
15
215
largest = l;
// If right child is larger than largest so far
if (r < n && arr[r] > arr[largest])
largest = r;
// If largest is not root
if (largest != i) {
swap(arr[i], arr[largest]);
int main()
{
// Array representation of Max-Heap
// 8
216
// / \
// 5 3
// / \
// 2 4
int arr[] = { 8, 5, 3, 4, 2 };
deleteRoot(arr, n);
cout<<"\n Array representation of heap After deletion\n";
printArray(arr, n);
return 0;
}
Output:
Question:
1. How many arrays are required to perform deletion operation in a
heap?
a. 1
b. 2
c. 3
d. 4
217
2. What is the time taken to perform a delete min operation?
a. O(N)
b. O(N log N)
c. O(log N)
d. O(N2)
Self-Learning Topics:
Expression Tree:
The expression tree is a binary tree in which each internal node
corresponds to the operator and each leaf node corresponds to the operand.
So, for example, expression tree for
4 + ((6+9) *3) would be:
4 *
+ 3
6 9
Heap Sort:
Heap sort is a comparison-based sorting technique based on Heap
data structure Heap sort involves building a Heap data structure from the
given array and then utilizing the Heap to sort the array.
218
Module VII
Experiment No:1
Aim:
Graph Creation using Adjacency matrix
Objective:
Writing C++ program for representation of a graph using
adjacency matrix.
Theory:
A Graph is a non-linear data structure consisting of nodes and
edges. The nodes are sometimes also referred to as vertices and the edges
are lines or arcs that connect any two nodes in the graph. In other words,
we can say that, A Graph consists of a finite set of vertices (or nodes) and
set of Edges which connect a pair of nodes.
Edge
0 4
1 2
Vertices
Graph
In the above Graph, the set of vertices V = {0,1,2,3,4} and the set of
edges E = {01, 12, 23, 34, 40, 14,24}.
Graph Terminology
Adjacency: A vertex is said to be adjacent to another vertex if there is an
edge connecting them. Vertices 2 and 0 are not adjacent because there is
no edge between them.
219
Path: A sequence of edges that allows you to go from vertex A to vertex
B is called a path. 0-1-2-4 is a path from vertex 0 to vertex 4.
Directed Graph: The edges in such a graph are represented by arrows to
show the direction of the edge.
Graph Representation:
The following are the two most commonly used representations of a
graph.
1. Adjacency Matrix
2. Adjacency List
Adjacency matrix representation of the Graph:
An adjacency matrix is used to represent adjacent nodes in the
graph. Two nodes are said to be adjacent if there is an edge connecting
them. We represent graph in the form of matrix in Adjacency matrix
representation. For a graph G, if there is an edge between two vertices a
and b then we denote it 1 in matrix. If there is no edge then denote it with
0 in matrix.
Adjacency Matrix is a 2D array of size V x V where V is the
number of vertices in a graph. Let the 2D array be adj [][], a slot adj[i][j] =
1 indicates that there is an edge from vertex i to vertex j. Adjacency matrix
for undirected graph is always symmetric. Adjacency Matrix is also used
to represent weighted graphs. If adj[i][j] = w, then there is an edge from
vertex i to vertex j with weight w.
Consider the following Graph and its Adjacency matrix Representation:
B D
Undirected Graph
220
Adjacency matrix representation of the above undirected graph:
A B C D
A 0 1 0 1
B 1 0 1 0
C 0 1 0 1
D 1 0 1 0
B D
Directed Graph
A 0 1 0 1
B 0 0 1 0
C 0 0 0 0
D 0 0 1 0
Algorithm:
1. Create a 2D array (say Adj[N+1] [N+1]) of size NxN and initialize
all value of this matrix to zero. Store all the edges of the graph in
arr [] [].
221
2. For each edge in the arr [][], Update value at Adj[X][Y] and
Adj[Y][X] to 1, denotes that there is a edge between X and Y.
3. Display the Adjacency Matrix after the above operation for all the
pairs in arr[][] is completed.
Program:
#include<iostream>
using namespace std;
int vertArr[20][20]; //the adjacency matrix initially 0
int count = 0;
void displayMatrix(int v) {
int i, j;
for(i = 0; i < v; i++) {
for(j = 0; j < v; j++) {
cout << vertArr[i][j] << " ";
}
cout << endl;
}
}
void add_edge(int u, int v) { //function to add edge into the matrix
vertArr[u][v] = 1;
vertArr[v][u] = 1;
}
int main() {
int v = 5; //there are 6 vertices in the graph
add_edge(0, 1);
add_edge(0, 2);
add_edge(0, 4);
add_edge(1, 3);
add_edge(3, 2);
add_edge(2, 4);
displayMatrix(v);
222
return 0;
}
Output:
1 2 4
Question:
1) Give various application of graph data structure in our daily life.
2) Given below the Adjacency matrix representation of the
graph,Draw the Graph:
223
A B C D
A 0 1 1 0
B 0 0 0 1
C 0 0 0 1
D 0 0 0 0
Experiment No:2
Aim:
Performing Breadth First Search (BFS) traversal on Graph data structure.
Objective:
Writing C++ program to perform BFS traversal on Graph.
Theory:
Graph Traversal:
There are two types of graph traversal algorithms. These are called the
Breadth First Search (BFS)and Depth First Search (DFS).
Breadth First Search (BFS)
The Breadth First Search (BFS) traversal is an algorithm, which is
used to visit all of the nodes of a given graph. In this traversal algorithm
one node is selected and then all of the adjacent nodes are visited one by
one. After completing all of the adjacent vertices, it moves further to
check another vertices and checks its adjacent vertices again. This process
will continue until all nodes are visited.
224
Here, are important rules for using BFS algorithm:
A queue (FIFO-First in First Out) data structure is used by BFS.
You mark any node in the graph as root and start traversing the
data from it.
BFS traverses all the nodes in the graph and keeps dropping them
as completed.
BFS visits an adjacent unvisited node, marks it as done, and inserts
it into a queue.
Removes the previous vertex from the queue in case no adjacent
vertex is found.
BFS algorithm iterates until all the vertices in the graph are
successfully traversed and marked as completed.
There are no loops caused by BFS during the traversing of data
from any node.
Consider the following graph:
2 3 5
4 Undirected Graph
Output:
Note: In the above program,while entering edges give space between two
vertexes of the edges.
227
Questions:
1. The Date structure used in standard implementation of Breadth
First Search is?
a) Stack
b) Queue
c) LinkedList
d) Tree
228
weight of a spanning tree is the sum of weights given to each edge of the
spanning tree.
A minimum spanning tree has (V – 1) edges where V is the
number of vertices in the given graph.
Consider the following weighted graph.
10
7 A B 4
5
6
3
F 2 E
2
8 C D
3
Weighted Graph
7 A B 4
5
6
3
F 2 E
2
8 C D
3
229
So, for our example it will be:
Weight Edge
2 BD
2 DE
3 CD
3 AC
4 BE
5 AB
6 CB
7 AF
8 FC
3) Now pick all edges one by one from the sorted list of edges
Pick edge B-D: No cycle is formed, include it.
2 E
2
D
2 E
3
2
C D
230
Pick edge A-C: No cycle is formed, include it.
A B
3
2 E
3
2
C D
Pick edge B-E: Since including this edge results in the cycle, discard it.
Pick edge A-B: Since including this edge results in the cycle, discard it.
Pick edge C-B: Since including this edge results in the cycle, discard it.
Pick edge A-F: No cycle is formed, include it.
A B
7
3
2 E
F
3
2
C D
Pick edge F-C: Since including this edge results in the cycle, discard it.
So, the final minimum spanning tree using Kruskal’s algorithm will be:
A B
7
3
2 E
F
3
2
C D
Algorithm:
Kruskal’s Algorithm
This algorithm will create spanning tree with minimum weight, from a
given weighted graph.
1. Begin
2. Remove loop and parallel edge.
3. Create the edge list of given graph, with their weights.
4. Sort the edge list according to their weights in ascending order.
231
5. Draw all the nodes to create skeleton for spanning tree.
6. Pick up the edge at the top of the edge list (i.e., edge with
minimum weight).
7. Remove this edge from the edge list.
8. Connect the vertices in the skeleton with given edge. If by
connecting the vertices, a cycle is created in the skeleton, then
discard this edge.
9. Repeat steps 5 to 7, until n-1 edges are added or list of edges is
over.
10. Return
Program:
// C++ program for Kruskal's algorithm
// to find Minimum Spanning Tree of a
// given connected, undirected and weighted
// graph
#include <bits/stdc++.h>
using namespace std;
// a structure to represent a
// weighted edge in graph
class Edge {
public:
int src, dest, weight;
};
232
// Creates a graph with V vertices and E edges
Graph* createGraph(int V, int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;
return graph;
}
return subsets[i].parent;
}
233
// rank tree (Union by Rank)
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
234
// Create V subsets with single elements
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
235
<< endl;
}
int main()
{
int V = 6; // Number of vertices in graph
int E = 8; // Number of edges in graph
Graph* graph = createGraph(V, E);
// Function call
KruskalMST(graph);
return 0;
}
Output:
Questions:
1. Every graph has only one minimum spanning tree.
a) True
b) False
237
3. Kruskal’s algorithm is a ______
a) divide and conquer algorithm
b) dynamic programming algorithm
c) greedy algorithm
d) approximation algorithm
What is the weight of the minimum spanning tree using the Kruskal’s
algorithm?
a) 24
b) 23
c) 15
d) 19
Self-Learning Topic:
Shortest Path algorithm:
In computer networks, the shortest path algorithms aim to find the optimal
paths between the network nodes so that routing cost is minimized.
Some common shortest path algorithms are −
1. Bellman Ford’s Algorithm
2. Dijkstra’s Algorithm
3. Floyd Warshall’s Algorithm
238