Professional Documents
Culture Documents
PROGRAM M I N G PERFOR MA N CE
The two appr o a c h e s which are use d to meas u r e the perfor m a n c e of the
progr a m are:
SPACE COMPLEXITY
Spa c e co m p l e x i t y is th e su m of th e foll o w i n g co m p o n e n t s :
(i) Ins t r u c t i o n sp a c e :
(ii) Dat a sp a c e :
2
(iii) Envir o n m e n t st a c k spa c e :
Retu r n addr e s s
Values of all local variabl e s and form al par a m e t e r s .
The Total spac e occupie d by the progr a m durin g the exec utio n of the
progr a m is the sum of the fixed spac e and the variabl e spac e.
(i) Fixed spa c e - The spac e occupi e d by the instr u c tio n spac e,
simple variable s and const a n t s .
(ii) Varia b l e spa c e – The dyna mic ally allocat e d spac e to the
various data stru c t u r e s and the enviro n m e n t stack spac e varies
accor di n g to the input from the user.
Sp a c e co m p l e x i t y S(P ) = c + S p
The tim e com ple xit y of the progra m depe n d s on the followin g
factors:
3
The total time take n for the exec utio n of the prog r a m is the sum of the
compilatio n time and the executio n time.
(i) Com p i l e tim e – The time take n for the compilatio n of the
progr a m to prod u c e the inter m e d i a t e object code or the
compile r version of the prog r a m . The compilatio n time is take n
only once as it is enou g h if the prog r a m is compile d once. If
optimize d code is to be gen e r a t e d , then the compila tion time
will be high e r.
Ti m e co m p l e x i t y T(P ) = c + T p
c à Compile time
T p à Run time or execu tio n time
(i) Identify one or more key oper a tio n s and dete r m i n e the num b e r of
times thes e are perfor m e d . That is find out how many key
oper a tio n s are pres e n t inside a loop and how many time s that loop
is execu t e d .
(ii) Dete r mi n e the total num b e r of step s execut e d by the prog r a m .
The time complexity will be propo r tio n al to the sum of the above two.
ASYMPTOTIC NOTATIO N S
Asympt otic nota tio n s – Asympt otic nota tio n s are the nota tio n s used to
desc rib e the beh avior of the time or spac e compl exity.
Let us rep r e s e n t the time complexity and the spac e complexity using the
com m o n function f(n).
4
(ii) Ω ( Ome g a notation )
(iii) θ ( Theta notation )
(iv) o ( Little Oh notation )
O – Big Oh notation
The big Oh nota tion provide s an upp e r boun d for the function f(n).
The function f(n) = O(g(n)) if and only if the r e exists positive cons t a n t s
c and n 0 such that f(n) ≤ cg(n) for all n ≥ n 0 .
Exam pl e s:
1. f(n) = 3n + 2
3n + 1 ≤ 4n for all n ≥ 2
2. f(n) = 10n 2 + 4n + 2
The Ω notatio n gives the lower boun d for the function f(n).
The function f(n) = Ω(g(n)) if and only if ther e exists positive const a n t s
c and n 0 such that f(n) ≥ cg(n) for all n ≥ n 0 .
Exam pl e s:
1. f(n) = 3n + 2
5
Let us check the above condition
3n + 1 ≥ 3n for all n ≥ 0
2. f(n) = 10n 2 + 4n + 2
θ – The t a not a t i o n
The thet a nota tion is use d whe n the function f(n) can be boun d e d by both
from above and below the sam e function g(n).
f(n) = θ (g(n)) if and only if ther e exists some positive const a n t s c 1 and c 2
and n 0 , such that c 1 g(n) ≤ f(n) ≤ c 2 g(n) for all n ≥ n 0 .
o - Littl e Oh not a t i o n
For exa m pl e,
6
SEARCHING AND SORTING
Searching is used to find the location where an element is available. There are two types of search
techniques. They are:
Sorting allows an efficient arrangement of elements within a given data structure. It is a way in which
the elements are organized systematically for some purpose. For example, a dictionary in which
words are arranged in alphabetical order and telephone director in which the subscriber names are
listed in alphabetical order. There are many sorting techniques out of which we study the following.
1. Bubble sort
2. Quick sort
3. Selection sort and
4. Heap sort
LINEAR SEARCH
This is the simplest of all searching techniques. In this technique, an ordered or unordered list will be
searched one by one from the beginning until the desired element is found. If the desired element is
found in the list then the search is successful otherwise unsuccessful.
Suppose there are ‘n’ elements organized sequentially on a List. The number of comparisons
required to retrieve an element from the list, purely depends on where the element is stored in the list.
If it is the first element, one comparison will do; if it is second element two comparisons are necessary
and so on. On an average you need [(n+1)/2] comparison’s to search an element. If search is not
successful, you would need ’n’ comparisons.
Algorithm:
Let array a[n] stores n elements. Determine whether element ‘x’ is present or not.
linsrch(a[n], x)
{
index = 0;
flag = 0;
while (index < n) do
{
if (x == a[index])
{
flag = 1;
break;
}
index ++;
}
if(flag == 1)
printf(“Data found at %d position“, index);
else
printf(“data not found”);
7
Example 1:
Suppose we have the following unsorted list: 45, 39, 8, 54, 77, 38, 24, 16, 4, 7, 9, 20
For any element not in the list, we’ll look at 12 elements before failure
Example 2:
Index 0 1 2 3 4 5 6 7 8
Elements -15 -6 0 7 9 23 54 82 101
# include <stdio.h>
# include <conio.h>
main()
{
int number[25], n, data, i, flag = 0;
clrscr();
printf("\n Enter the number of elements: ");
scanf("%d", &n);
printf("\n Enter the elements: ");
for(i = 0; i < n; i++)
scanf("%d", &number[i]);
printf("\n Enter the element to be Searched: ");
scanf("%d", &data);
for( i = 0; i < n; i++)
{
if(number[i] == data)
{
flag = 1;
break;
}
}
if(flag == 1)
printf("\n Data found at location: %d", i+1);
else
printf("\n Data not found ");
8
}
# include <stdio.h>
# include <conio.h>
void main()
{
int a[25], i, n, data;
clrscr();
printf("\n Enter the number of elements: ");
scanf("%d", &n);
printf("\n Enter the elements: ");
for(i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
printf("\n Enter the element to be seached: ");
scanf("%d", &data);
linear_search(a, data, 0, n);
getch();
}
BINARY SEARCH
If we have ‘n’ records which have been ordered by keys so that x 1 < x2 < … < xn . When we are given a
element ‘x’, binary search is used to find the corresponding element from the list. In case ‘x’ is
present, we have to determine a value ‘j’ such that a[j] = x (successful search). If ‘x’ is not in the list
then j is to set to zero (un successful search).
In Binary search we jump into the middle of the file, where we find key a[mid], and compare ‘x’ with
a[mid]. If x = a[mid] then the desired record has been found. If x < a[mid] then ‘x’ must be in
that portion of the file that precedes a[mid]. Similarly, if a[mid] > x, then further search is only
necessary in that part of the file which follows a[mid]. If we use recursive procedure of finding the
middle key a[mid] of the un-searched portion of a file, then every un-successful comparison of ‘x’ with
a[mid] will eliminate roughly half the un-searched portion from consideration.
Since the array size is roughly halved after each comparison between ‘x’ and a[mid], and since an
array of length ‘n’ can be halved only about log 2n times before reaching a trivial length, the worst case
complexity of Binary search is about log2n
Algorithm:
9
Let array a[n] of elements in increasing order, n 0, determine whether ‘x’ is present, and if so, set j
such that x = a[j] else return 0.
binsrch(a[], n, x)
{
low = 1; high = n;
while (low < high) do
{
mid = (low + high)/2
if (x < a[mid])
high = mid – 1;
else if (x > a[mid])
low = mid + 1;
else return mid;
}
return 0;
}
low and high are integer variables such that each time through the loop either ‘x’ is found or low is
increased by at least one or high is decreased by at least one. Thus we have two sequences of
integers approaching each other and eventually low will become greater than high causing
termination in a finite number of steps if ‘x’ is not present.
Example 1:
Index 1 2 3 4 5 6 7 8 9 10 11 12
Elements 4 7 8 9 16 20 24 38 39 45 54 77
If we are searching for x = 4: (This needs 3 comparisons)
low = 1, high = 12, mid = 13/2 = 6, check 20
low = 1, high = 5, mid = 6/2 = 3, check 8
low = 1, high = 2, mid = 3/2 = 1, check 4, found
10
low = 7, high = 7, mid = 14/2 = 7, check 24, found
Summing the comparisons, needed to find all twelve items and dividing by 12, yielding 37/12 or
approximately 3.08 comparisons per successful search on the average.
Example 2:
Index 1 2 3 4 5 6 7 8 9
Elements -15 -6 0 7 9 23 54 82 101
11
low high mid
1 9 5
6 9 7
5 6 5
6 6 6
7 6 not found
Continuing in this manner the number of element comparisons needed to find each of nine elements
is:
Index 1 2 3 4 5 6 7 8 9
Elements -15 -6 0 7 9 23 54 82 101
Comparisons 3 2 3 4 1 3 2 3 4
No element requires more than 4 comparisons to be found. Summing the comparisons needed to find
all nine items and dividing by 9, yielding 25/9 or approximately 2.77 comparisons per successful
search on the average.
There are ten possible ways that an un-successful search may terminate depending upon the value of
x.
If x < a(1), a(1) < x < a(2), a(2) < x < a(3), a(5) < x < a(6), a(6) < x < a(7) or a(7) < x < a(8) the
algorithm requires 3 element comparisons to determine that ‘x’ is not present. For all of the remaining
possibilities BINSRCH requires 4 element comparisons. Thus the average number of element
comparisons for an unsuccessful search is:
(3 + 3 + 3 + 4 + 4 + 3 + 3 + 3 + 4 + 4) / 10 = 34/10 = 3.4
Time Complexity:
The time complexity of binary search in a successful search is O(log n) and for an unsuccessful
search is O(log n).
A non-recursive program for binary search:
# include <stdio.h>
# include <conio.h>
main()
{
int number[25], n, data, i, flag = 0, low, high, mid;
clrscr();
printf("\n Enter the number of elements: ");
scanf("%d", &n);
printf("\n Enter the elements in ascending order: ");
for(i = 0; i < n; i++)
scanf("%d", &number[i]);
printf("\n Enter the element to be searched: ");
scanf("%d", &data);
low = 0; high = n-1;
while(low <= high)
{
mid = (low + high)/2;
if(number[mid] == data)
12
{
flag = 1;
break;
}
else
{
if(data < number[mid])
high = mid - 1;
else
low = mid + 1;
}
}
if(flag == 1)
printf("\n Data found at location: %d", mid + 1);
else
printf("\n Data Not Found ");
}
# include <stdio.h>
# include <conio.h>
void main()
{
int a[25], i, n, data;
clrscr();
printf("\n Enter the number of elements: ");
scanf("%d", &n);
printf("\n Enter the elements in ascending order: ");
for(i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("\n Enter the element to be searched: ");
scanf("%d", &data);
bin_search(a, data, 0, n-1);
getch();
}
Bubble Sort:
The bubble sort is easy to understand and program. The basic idea of bubble sort is to pass through
the file sequentially several times. In each pass, we compare each element in the file with its
13
successor i.e., X[i] with X[i+1] and interchange two element when they are not in proper order. We will
illustrate this sorting technique by taking a specific example. Bubble sort is also called as exchange
sort.
Suppose we want our array to be stored in ascending order. Then we pass through the array 5 times
as described below:
We compare X[i] and X[i+1] for i = 0, 1, 2, 3, and 4, and interchange X[i] and X[i+1] if X[i] > X[i+1]. The
process is shown below:
The biggest number 66 is moved to (bubbled up) the right most position in the array.
We repeat the same process, but this time we don’t include X[5] into our comparisons. i.e., we
compare X[i] with X[i+1] for i=0, 1, 2, and 3 and interchange X[i] and X[i+1] if X[i] > X[i+1]. The
process is shown below:
We repeat the same process, but this time we leave both X[4] and X[5]. By doing this, we move the
third biggest number 44 to X[3].
14
22 33
33 44
11 22 33 44
We repeat the process leaving X[3], X[4], and X[5]. By doing this, we move the fourth biggest number
33 to X[2].
We repeat the process leaving X[2], X[3], X[4], and X[5]. By doing this, we move the fifth biggest
number 22 to X[1]. At this time, we will have the smallest number 11 in X[0]. Thus, we see that we
can sort the array of size 6 in 5 passes.
#include <stdio.h>
#include <conio.h>
main()
{
int i, n, x[25];
clrscr();
printf("\n Enter the number of elements: ");
scanf("%d",&n);
printf("\n Enter Data:");
for(i = 0; i < n ; i++)
scanf("%d", &x[i]);
bubblesort(x,n);
printf ("\nArray Elements after sorting: ");
for (i = 0; i < n; i++)
15
printf ("%5d", x[i]);
}
Time Complexity:
The bubble sort method of sorting an array of size n requires (n-1) passes and (n-1) comparisons on
each pass. Thus the total number of comparisons is (n-1) * (n-1) = n 2 – 2n + 1, which is O(n 2).
Therefore bubble sort is very inefficient when there are more elements to sorting.
Selection Sort:
Now, you will learn another sorting technique, which is more efficient than bubble sort and the
insertion sort. This sort, as you will see, will not require no more than n-1 interchanges. The sort we
are talking about is selection sort.
Suppose x is an array of size n stored in memory. The selection sort algorithm first selects the
smallest element in the array x and place it at array position 0; then it selects the next smallest
element in the array x and place it at array position 1. It simply continues this procedure until it places
the biggest element in the last position of the array. We will now present to you an algorithm for
selection sort.
The array is passed through (n-1) times and the smallest element is placed in its respective position
in the array as detailed below:
Pass 1:
Find the location j of the smallest element in the array x [0], x[1], . . . . x[n-1], and then interchange x[j]
with x[0]. Then x[0] is sorted.
Pass 2:
Leave the first element and find the location j of the smallest element in the sub-array x[1], x[2], . . . .
x[n-1], and then interchange x[1] with x[j]. Then x[0], x[1] are sorted.
Pass 3:
Leave the first two elements and find the location j of the smallest element in the sub-array x[2], x[3], .
. . . x[n-1], and then interchange x[2] with x[j]. Then x[0], x[1], x[2] are sorted.
Pass (n-1):
Find the location j of the smaller of the elements x[n-2] and x[n-1], and then interchange x[j] and x[n-
2]. Then x[0], x[1], . . . . x[n-2] are sorted. Of course, during this pass x[n-1] will be the biggest
element and so the entire array is sorted.
Time Complexity:
In general we prefer selection sort in case where the insertion sort or the bubble sort requires
exclusive swapping. In spite of superiority of the selection sort over bubble sort and the insertion sort
(there is significant decrease in run time), its efficiency is also O(n 2) for n data items.
Example:
Let us consider the following example with 9 elements to analyze selection Sort:
1 2 3 4 5 6 7 8 9 Remarks
16
45 50 55 80 70 60 75 85 65 Find the fourth smallest element
# include<stdio.h>
# include<conio.h>
int a[25];
int main()
{
int num, i= 0;
clrscr();
printf( "Enter the number of elements: " );
scanf("%d", &num);
printf( "\nEnter the elements:\n" );
for(i=0; i < num; i++)
scanf( "%d", &a[i] );
selectionSort( 0, num - 1 );
printf( "\nThe elements after sorting are: " );
for( i=0; i< num; i++ )
printf( "%d ", a[i] );
return 0;
}
#include <stdio.h>
17
#include<conio.h>
selectionSort(int);
main()
{
int i, n = 0;
clrscr();
printf (" Array Elements before sorting: ");
for (i=0; i<5; i++)
printf ("%d ", x[i]);
selectionSort(n); /* call selection sort */
printf ("\n Array Elements after sorting: ");
for (i=0; i<5; i++)
printf ("%d ", x[i]);
}
selectionSort( int n)
{
int k, p, temp, min;
if (n== 4)
return (-1);
min = x[n];
p = n;
for (k = n+1; k<5; k++)
{
if (x[k] <min)
{
min = x[k];
p = k;
}
}
temp = x[n]; /* interchange x[n] and x[p] */
x[n] = x[p];
x[p] = temp;
n++ ;
selectionSort(n);
}
INSERTIO N SORT
The main idea behin d the inser tion sort is to inser t the i th elem e n t
in its corr e c t place in the i th pass. Suppo s e an array A with n elem e n t s
A[1], A[2],…A[N] is in mem o ry. The inse r tio n sort algorit h m scans A
from A[1] to A[N], inse rtin g each elem e n t A[K] into its prop e r position in
the previously sort e d suba r r a y A[1], A[2],..A[K-1].
Prin c i p l e : In Inser tion Sort algorith m , each ele m e n t A[K] in the list is
com p ar e d with all the ele m e n t s befor e it ( A[1] to A[K-1]). If any
ele m e n t A[I] is found to be great er than A[K] then A[K] is inser t e d in
the place of A[I}. This proce s s is repeat e d till all the ele m e n t s are
sorte d.
Alg o r i t h m :
18
Proc e d u r e INSERTIO N S O R T (A, N)
Last ß N – 1
Exa m p l e :
i = 0 i =1 i = 2 i = 3 i = 4 i = 5 i = 6 i = 7 i = 8 i = 9
42 23 74 11 65 58 94 36 99 87
P= 1 A[P] < A[0] à Inser t A[P] at 0 L= 9
23 42 74 11 65 58 94 36 99 87
P= 2 L= 9
A[P] is great e r than all ele m e n t s befor e it. Henc e No Chang e
19
23 42 74 11 65 58 94 36 99 87
P= 3 A[P] < A[0] à Inser t A[P] at 0 L= 9
11 23 42 74 65 58 94 36 99 87
P= 4 L= 9
A[P] < A[3] à Inser t A[P] at 3
11 23 42 65 74 58 94 36 99 87
P= 5 L= 9
A[P] < A[3] à Inser t A[P] at 3
11 23 42 58 65 74 94 36 99 87
P= 6 L= 9
A[P] is great e r than all ele m e n t s befor e it. Henc e No Chang e
11 23 42 58 65 74 94 36 99 87
P= 7 L= 9
A[P] < A[2] à Inser t A[P] at 2
11 23 36 42 58 65 74 94 99 87
P= 8 L= 9
A[P] is great e r than all ele m e n t s befor e it. Henc e No Chang e
11 23 36 42 58 65 74 94 99 87
P, L=9
A[P] < A[7] à Inser t A[P] at 7
Sort e d List:
11 23 36 42 58 65 74 87 94 99
Pro g r a m :
20
if (a[pas s] < a [i])
{
tem p = a [ p a s s ];
for (int j=p a s s- 1;j> = i ;j- -)
a[j + 1] = a [j];
a[i] = t e m p ;
}
}
}
}
In the sort function, the integ e r variabl e last is use d to point to the
last elem e n t in the list. The first pass star t s with the varia bl e pass
pointing to the secon d elem e n t and contin u e s till pass rea c h e s the last
elem e n t . In each pass, a[pas s] is comp a r e d with all the elem e n t s before
it and if a[pas s] is lesse r than a[i], then it is insert e d in position i. Before
inserti n g it, the elem e n t s a[i] to a[pas s- 1] are shifte d right using a
tem p o r a r y variable.
Adva n t a g e s :
1. Sort s the list faste r whe n the list has less num b e r of elem e n t s .
2. Efficient in case s wher e a new elem e n t has to be inser t e d into a
sort e d list.
Dis a d v a n t a g e s :
1. Very slow for large values of n.
2. Poor perfor m a n c e if the list is in almost reve r s e orde r.
21
Quick Sort
The quick sort was invented by Prof. C. A. R. Hoare in the early 1960’s. It was one of the first more
efficient sorting algorithms. It is an example of a class of algorithms that work by what is usually called
“divide and conquer”.
In essence, the quick sort algorithm partitions the original array by rearranging it into two groups. The
first group contains those elements less than some arbitrary chosen value taken from the set, and the
second group contains those elements greater than or equal to the chosen value.
The chosen value is known as the pivot element. Once the array has been rearranged in this way with
respect to the pivot, the very same partitioning is recursively applied to each of the two subsets.
When all the subsets have been partitioned and rearranged, the original array is sorted.
The function partition() makes use of two pointers up and down which are moved toward each other
in the following fashion:
1. Repeatedly increase the pointer up by one position until a[up] > =pivot.
2. Repeatedly decrease the pointer down by one position until a[down] <=pivot.
4. Repeat the steps 1, 2 and 3 till the ‘up’ pointer crosses the ‘down’ pointer. If ‘up’ pointer
crosses ‘down’ pointer, the position for pivot is found and place pivot element in ‘down’
pointer position.
The program uses a recursive function quicksort(). The algorithm of quick sort function sorts all
elements in an array ‘a’ between positions ‘low’ and ‘high’.
1. It terminates when the condition low >= high is satisfied. This condition will be satisfied
only when the array is completely sorted.
2. Here we choose the first element as the ‘pivot’. So, pivot = x[low]. Now it calls the
partition function to find the proper position j of the element x[low] i.e. pivot. Then we will
have two sub-arrays x[low], x[low+1], . . . . . . . x[j-1] and x[j+1], x[j+2], . . .x[high].
3. It calls itself recursively to sort the left sub-array x[low], x[low+1], . . . . . . . x[j-1] between
positions low and j-1 (where j is returned by the partition function).
4. It calls itself recursively to sort the right sub-array x[j+1], x[j+2], . . .x[high] between
positions j+1 and high.
Algorithm
Sorts the elements a[p], . . . . . ,a[q] which reside in the global array a[n] into ascending order. The a[n
+ 1] is considered to be defined and must be greater than all elements in a[n]; a[n + 1] = +
quicksort (p, q)
{
if ( p < q ) then
{
call j = PARTITION(a, p, q+1); // j is the position of the partitioning element
call quicksort(p, j – 1);
call quicksort(j + 1 , q);
}
}
partition(a, m, p)
{
v = a[m]; up = m; down = p; // a[m] is the partition element
do
{
22
repeat
up = up + 1;
until (a[up] > v);
repeat
down = down – 1;
until (a[down] < v);
if (up < down) then call interchange(a, up, down);
} while (up > down);
a[m] = a[down];
a[down] = v;
return (down);
}
Time complexity:
There are several choices for choosing the ‘pivot’ element through which we can improve the
efficiency of quick sort. For example, one may choose the ‘pivot’ element as median or mean or
middle element. Also, a non-recursive method could be developed for execution efficiency. When
these improvements are made, experiments indicate the fact that the total number of comparisons for
quick sort is of O(n log n).
Example:
Select first element as the pivot element. Move ‘up’ pointer from left to right in search of an element
larger than pivot. Move the ‘down’ pointer from right to left in search of an element smaller than pivot.
If such elements are found, the elements are swapped. This process continues till the ‘up’ pointer
crosses the ‘down’ pointer. If ‘up’ pointer crosses ‘down’ pointer, the position for pivot is found and
interchange pivot and element at ‘down’ position.
Let us consider the following example with 13 elements to analyze quick sort:
1
2 3 4 5 6 7 8 9 10 11 12 13 Remarks
38 08 16 06 79 57 24 56 02 58 04 70 45
dow swap up
pivot up
n & down
04 79
dow swap up
up
n & down
02 57
dow
up
n
swap
(24 08 16 06 04 02) 38 (56 57 58 79 70 45) pivot &
down
swap
dow
pivot pivot &
n
down
(02 08 16 06 04) 24
pivot, up swap
down pivot &
23
down
02 (08 16 06 04)
dow swap up
pivot up
n & down
04 16
dow
Up
n
swap
(06 04) 08 pivot &
(16)
down
pivot
,
up
dow
n
swap
(04) 06 pivot &
down
04
pivot
,
dow
n
16
pivot
,
dow
n
(02 04 06 08 16 24) 38
(56 57 58 79 70 45)
dow swap up
pivot up
n & down
45 57
dow
up
n
swap
(45) 56 (58 79 70 57) pivot &
down
45
pivot swap
, pivot &
dow down
n
57)
(58 79 swap up
70 dow
pivot up & down
n
57 79
dow
up
n
swap
(57) 58 (70 79) pivot &
down
57
pivot
,
dow
n
(70 79)
pivot
swap
,
up pivot &
dow
down
n
70
79
pivot
,
dow
24
n
(45 56 57 58 70 79)
02 04 06 08 16 24 38 45 56 57 58 70 79
# include<stdio.h>
# include<conio.h>
int array[25];
int main()
{
int num, i = 0;
clrscr();
printf( "Enter the number of elements: " );
scanf( "%d", &num);
printf( "Enter the elements: " );
for(i=0; i < num; i++)
scanf( "%d", &array[i] );
quicksort(0, num -1);
printf( "\nThe elements after sorting are: " );
for(i=0; i < num; i++)
printf("%d ", array[i]);
return 0;
}
void quicksort(int low, int high)
{
int pivotpos;
if( low < high )
{
pivotpos = partition(low, high + 1);
quicksort(low, pivotpos - 1);
quicksort(pivotpos + 1, high);
}
}
do
{
do
up = up + 1;
while(array[up] < pivot );
do
down = down - 1;
while(array[down] > pivot);
25
array[low] = array[down];
array[down] = pivot;
return down;
}
Heap is a data structure, which permits one to insert elements into a set and also to find the largest
element efficiently. A data structure, which provides these two operations, is called a priority queue.
A max heap is an almost complete binary tree such that the value of each node is greater than or
equal to those in its children.
95 15
85 45 45 25
75 25 35 15 55 65 35 75
55 65 85 95 Min h e a p
Max he ap
A min heap is an almost complete binary tree such that the value of each node is less than or equal to
those in its children.
Since heap is a complete binary tree, a heap tree can be efficiently represented using one
dimensional array. This provides a very convenient way of figuring out where children belong to.
The elements of the array can be thought of as lying in a tree structure. A heap tree represented
using a single array looks as follows:
26
x[ 1]
65 x[ 3]
x[ 2]
45 60
x[ 6] x[ 7]
x[ 4] 40 x[ 5] 25 50 55
x[ 8] 30 He a p Tr e e
1. Insertion,
2. Deletion and
3. Merging.
Insertion into a heap tree:
This operation is used to insert a node into an existing heap tree satisfying the properties of heap
tree. Using repeated insertions of data, starting from an empty heap tree, one can build up a heap
tree.
Let us consider the heap (max) tree. The principle of insertion is that, first we have to adjoin the data
in the complete binary tree. Next, we have to compare it with the data in its parent; if the value is
greater than that at parent then interchange the values. This will continue between two nodes on path
from the newly inserted node to the root node till we get a parent whose value is greater than its child
or we reached the root.
For illustration, 35 is added as the right child of 80. Its value is compared with its parent’s value, and
to be a max heap, parent’s value greater than child’s value is satisfied, hence interchange as well as
further comparisons are no more required.
As another illustration, let us consider the case of insertion 90 into the resultant heap tree. First, 90
will be added as left child of 40, when 90 is compared with 40 it requires interchange. Next, 90 is
compared with 80, another interchange takes place. Now, our process stops here, as 90 is now in
root node. The path on which these comparisons and interchanges have taken places are shown by
dashed line.
The algorithm Max_heap_insert to insert a data into a max heap tree is as follows:
Max_heap_insert (a, n)
{
//inserts the value in a[n] into the heap which is stored at a[1] to a[n-1]
integer i, n;
i = n;
item = a[n] ;
while ( (i > 1) and (a[ i/2 ] < item ) do
{
a[i] = a[ i/2 ] ; // move the parent down
i = i/2 ;
}
a[i] = item ;
return true ;
}
Example:
Form a heap by using the above algorithm for the given data 40, 80, 35, 90, 45, 50, 70.
27
1. Insert 40:
40
2. Insert 80:
80
40 80
40
80 40
28
3. I n s ert 3 5:
80
40 35
4. I n s ert 9 0:
90
80 90
80
90
40 35 80 35
40
90 40
5. I n s ert 4 5:
90
80 35
40 45
6. I n s ert 5 0:
90 90
50
80 35 80 50
35
40 45 50 40 45 35
7. I n s ert 7 0:
90 90
70
80 50 80 70
50
40 45 35 70 40 45 35 50
adjust (a, i, n)
// The complete binary trees with roots a(2*i) and a(2*i + 1) are combined with a(i) to form a single
heap, 1 < i < n. No node has an address greater than n or less than 1. //
{
j = 2 *i ;
item = a[i] ;
while (j < n) do
29
{
if ((j < n) and (a (j) < a (j + 1)) then j ß j + 1;
// compare left and right child and let j be the larger child
if (item > a (j)) then break;
// a position for item is found
else a[ j / 2 ] = a[j] // move the larger child up a level
j = 2 * j;
}
a [ j / 2 ] = item;
}
Here the root node is 99. The last node is 26, it is in the level 3. So, 99 is replaced by 26 and this
node with data 26 is removed from the tree. Next 26 at root node is compared with its two child 45
and 63. As 63 is greater, they are interchanged. Now, 26 is compared with its children, namely, 57
and 42, as 57 is greater, so they are interchanged. Now, 26 appears as the leave node, hence re-
heap is completed.
26 63
99
26 63
57
45 63
45 57
26
35 29 57 42
35 29 26 42
27 12 24 26
27 12 24
D e l e t i n g t h e n o d e w it h d a t a 9 9 Af t e r D e l e t i o n o f n o d e w it h d a t a 9 9
HEAP SORT:
A heap sort algorithm works by first organizing the data to be sorted into a special type of binary tree
called a heap. Any kind of data can be sorted either in ascending order or in descending order using
heap tree. It does this with the following steps:
Algorithm:
This algorithm sorts the elements a[n]. Heap sort rearranges them in-place in non-decreasing order.
First transform the elements into a heap.
heapsort(a, n)
{
heapify(a, n);
for i = n to 2 by – 1 do
{
temp = a[I];
a[i] = a[1];
a[1] = t;
adjust (a, 1, i – 1);
}
30
}
heapify (a, n)
//Readjust the elements in a[n] to form a heap.
{
for i ß n/2 to 1 by – 1 do adjust (a, i, n);
}
adjust (a, i, n)
// The complete binary trees with roots a(2*i) and a(2*i + 1) are combined with a(i) to form a single
heap, 1 < i < n. No node has an address greater than n or less than 1. //
{
j = 2 *i ;
item = a[i] ;
while (j < n) do
{
if ((j < n) and (a (j) < a (j + 1)) then j ß j + 1;
// compare left and right child and let j be the larger child
if (item > a (j)) then break;
// a position for item is found
else a[ j / 2 ] = a[j] // move the larger child up a level
j = 2 * j;
}
a [ j / 2 ] = item;
}
Time Complexity:
Each ‘n’ insertion operations takes O(log k), where ‘k’ is the number of elements in the heap at the
time.
Likewise, each of the ‘n’ remove operations also runs in time O(log k), where ‘k’ is the number of
elements in the heap at the time.
Since we always have k ≤ n, each such operation runs in O(log n) time in the worst case.
Thus, for ‘n’ elements it takes O(n log n) time, so the priority queue sorting algorithm runs in O(n log
n) time when we use a heap to implement the priority queue.
Example 1:
Form a heap from the set of elements (40, 80, 35, 90, 45, 50, 70) and sort the data using heap sort.
Solution:
First form a heap tree from the given set of data and then sort by repeated deletion operation:
31
40 40
80 35 80 70
90 45 50 70 90 45 50 35
90
40
40 70
90 70
80 45 50 35
80 45 50 35
70
35
35
35
90
80 70
40 45 50 35
32
1. E x c h a n g e r o o t 9 0 w it h t h e l a s t e l e m e n t 3 5 o f t h e a r r a y a n d r e - h e a p if y
80
35 80
45 35
80 70 45 70
40 45 50 90 40 35 50 90
35
2. E x c h a n g e r o o t 8 0 w it h t h e l a s t e l e m e n t 5 0 o f t h e a r r a y a n d r e - h e a p if y
70
50 70
50
45 70 45 50
40 35 80 90 40 35 80 90
3. E x c h a n g e r o o t 7 0 w it h t h e l a s t e l e m e n t 3 5 o f t h e a r r a y a n d r e - h e a p if y
50
35 50
35
45 50 45 35
40 70 80 90 40 70 80 90
4. E x c h a n g e r o o t 5 0 w it h t h e l a s t e l e m e n t 4 0 o f t h e a r r a y a n d r e - h e a p if y
45
40 45
40
45 35 40 35
50 70 80 90 50 70 80 90
5. E x c h a n g e r o o t 4 5 w it h t h e l a s t e l e m e n t 3 5 o f t h e a r r a y a n d r e - h e a p if y
40
35 40
35
40 45 35 45
50 70 80 90 50 70 80 90
6. E x c h a n g e r o o t 4 0 w it h t h e l a s t e l e m e n t 3 5 o f t h e a r r a y a n d r e - h e a p if y
35
40 35
40
35 45 40 45
50 70 80 90 50 70 80 90
Th e s ort e d t r e e
33
# include <stdio.h>
# include <conio.h>
void main()
{
int i, n, a[20];
clrscr();
printf("\n How many element you want: ");
scanf("%d",&n);
printf("Enter %d elements: ",n);
for (i=1;i<=n;i++)
scanf("%d", &a[i]);
heapsort(n, a);
printf("\n The sorted elements are: \n");
for (i=1;i<=n;i++)
printf("%5d",a[i]);
getch();
}
MERGE SORT
34
Prin c i p l e : The given list is divide d into two roughly equal parts called
the left and the right subfiles. Thes e subfiles are sorte d using the
algorith m recursiv el y and then the two subfiles are mer g e d toget h e r to
obtain the sorte d file.
Alg o r i t h m :
If I > mid
Then
While J ≤ high
Temp[K] ß A[J]
KßK+ 1
JßJ+ 1
End While
Else
While I ≤ mid
Temp[K] ß A[I]
KßK+ 1
IßI+ 1
End While
End If
35
Proc e d u r e MERGE SO RT (A, low, hig h )
Exa m p l e :
i = 0 i =1 i = 2 i = 3 i = 4 i = 5 i = 6 i = 7 i = 8 i = 9
42 23 74 11 65 58 94 36 99 87
U M H
In each pass the mid value is calcula t e d and base d on that the list is split
into two. This is done recu r s iv ely and at last N num b e r of lists each
having only one elem e n t is produ c e d as show n.
36
Now mer gi n g oper a tio n is called on first two lists to produ c e a single
sort e d list, then the sam e thing is done on the next two lists and so on.
Finally a single sort e d list is obtain e d .
Pro g r a m :
if (i> mi d)
while (j< = h i g h )
tem p[k + + ] = a [ j + + ] ;
else
while (i< = m i d )
tem p[k + + ] = a [ i + + ] ;
37
for (k=low; k< = h i g h ; k+ + )
a[k] = t e m p [ k];
}
Adva n t a g e s :
Dis a d v a n t a g e s :
1. Nee d s a tem po r a r y arr ay every time, for storin g the new sort e d
list.
shell Sort
The sh e l l sort , som eti m e s called the “diminis hin g incre m e n t sort,”
improv e s on the inser tion sort by bre aki n g the original list into a num b e r
of smalle r sublist s, each of which is sorte d using an inser tio n sort. The
uniqu e way that thes e sublists are chos e n is the key to the shell sort.
Inste a d of bre a ki n g the list into sublists of contigu o u s item s, the shell
sort uses an incre m e n t i, some ti m e s called the gap , to crea t e a sublist by
choosin g all item s that are i items apa r t.
Exam pl e of shell Sort : Use Shell sort for the following arr ay : 18, 32, 12,
5, 38, 30, 16, 2
38
Comp a r e the elem e n t s at a gap of 2 i.e 18 with 12 and so on.
Now the gap is 1. So now use insertio n sort to sort this arr ay.
39
UNIT- II
STACKS
Oper a t i o n s on Sta c k:
Ther e are two possible oper a tio n s done on a stack. They are pop
and pus h oper a ti o n.
The Stack can be imple m e n t e d using both arr ays and linke d lists.
When dyna mic memo ry allocation is prefe r r e d we go for linked lists to
imple m e n t the stacks.
Pu s h op er a t i o n :
If the elem e n t s are add e d contin uo u s ly to the stack using the push
oper a tio n then the stack grow s at one end. Initially when the stack is
empty the top = -1. The top is a variabl e which indica t e s the position of
the topmo s t elem e n t in the stack.
40
PUS H ( x )
If top = MAX – 1
Then
Print “Stack is full”
Retu r n
Else
Top = top + 1
A[top] = x
End if
End PUSH( )
Pop op er a t i o n :
POP( )
If top = -1
Then
Print “Stack is empty”
Retu r n
Else
Item = A[top]
A[Top] = 0
Top = top – 1
Retu r n item
End if
End POP( )
Pro g r a m :
41
// Stack and various oper a tio n s on it
#i n cl u d e <ios t r e a m . h >
#i n cl u d e <co nio. h >
};
stack::s t a c k()
{
top =- 1;
}
42
}
}
Ou t p u t :
40
30
20
10
Poppe d item: 4 0
Poppe d item: 3 0
20
10
Pu s h op er a t i o n :
Crea t e a temp o r a r y node and stor e the value of x in the dat a part
of the node. Now make link part of temp point to Top and then top point
to Temp. That will make the new node as the topm os t elem e n t in the
stack.
43
PUS H ( x )
Info(te m p) = x
Link(te m p ) = top
Top = tem p
End PUSH( )
Pop op er a t i o n
POP( )
If Top = NULL
Then
Print “Stack is empty”
Retu r n
Else
Item = info(top)
Temp = top
44
Top = link(top)
Delete tem p
Retu r n item
End if
End POP( )
Pro g r a m :
#i n cl u d e <ios t r e a m . h >
#i n cl u d e <co nio. h >
class stack
{
privat e:
stru c t node
{
int data;
node *link;
};
node *top;
public:
stack();
~ s t a c k ();
void push(int x);
int pop();
void display();
};
stack::s t a c k()
{
top = N U LL;
}
stack:: ~ s t a c k ()
{
node *temp;
while (top! = N U LL)
{
tem p = t o p- >link;
delet e top;
top = t e m p ;
}
}
45
tem p = n e w node;
tem p- > d a t a = x ;
tem p- >link = t o p ;
top = t e m p ;
}
void main()
{
clrsc r();
stack s;
int n;
s.pus h( 1 0);
s.pus h( 2 0);
s.pus h( 3 0);
s.pus h( 4 0);
s.displ ay();
n= s. p o p();
cout < < " \ n P o p p e d item:" < < n ;
n= s. p o p();
cout < < " \ n P o p p e d item:" < < n ;
s.displ ay();
getch();
}
Ou t p u t :
40
46
30
20
10
Poppe d item: 4 0
Poppe d item: 3 0
20
10
APPLICATIO N OF STACKS
A+ B
+ AB
AB +
Henc e the given expre s sio n in infix form is first conve r t e d to postfix form
and then evalu a t e d to get the res ults.
47
and the char a c t e r popp e d ‘opr’ are comp a r e d . Then
following step s are perfor m e d as per the prec e d e n c e rule.
i. If ‘opr’ has highe r or sam e priority as the cha r a c t e r
scan n e d , the n opr is adde d to the targ e t strin g.
ii. If opr has lower prec e d e n c e than the char a c t e r
scan n e d , then the loop is ter mi n a t e d . Opr is push e d
back to the stack. Then, the char a c t e r scan n e d is also
add e d to the stack.
(e) If the cha r a c t e r scan n e d happ e n s to be an openin g
par e n t h e s i s, then the oper a t o r s pres e n t in the stack are
ret riev e d throu g h a loop. The loop contin u e s till it does not
encou n t e r a closing par e n t h e s i s . The oper a t o r s popp e d , are
add e d to the targ e t string pointe d to by t.
2. Now the strin g point e d by t is the requir e d postfix expr e s sio n.
Pro g r a m :
#i n cl u d e <ios t r e a m . h >
#i n cl u d e <s t ri n g. h >
#i n cl u d e <c ty p e. h >
#i n cl u d e <co nio. h >
class infix
{
privat e:
public:
infix();
void push(c h a r c);
char pop();
void conver t( c h a r *str);
int priority (cha r c);
void show();
};
infix::infix()
{
top =- 1;
strcpy(t a r g e t ,"");
strcpy(st a c k,"");
t= t a r g e t ;
s="";
48
}
char infix::pop()
{
if (top = = - 1)
{
cout < < " \ n S t a c k is empty\n";
ret u r n -1;
}
else
{
char item = s t a c k [ t o p ];
top- -;
ret u r n item;
}
}
void infix::conve r t( c h a r *str)
{
s= s t r;
while(*s! = ' \ 0 ')
{
if (*s = = ' '||*s = = ' \ t ')
{
s+ + ;
contin u e;
}
if (isdigit(*s) || isalph a(*s))
{
while(isdigit(*s) || isalph a(*s))
{
*t=*s;
s+ + ;
t+ + ;
}
}
if (*s = = ' ( ')
{
pus h(*s);
s+ + ;
49
}
char opr;
if (*s = = '*' | |*s = = ' + ' | | * s = = ' / ' | |* s = = ' % ' | |* s = = ' - '||*s = = ' ^ ' )
{
if (top! =- 1)
{
opr = p o p ();
while (priority(op r) > = p r i o r i t y(*s))
{
*t=o p r;
t+ + ;
opr = p o p ();
}
pus h(o p r);
pus h(*s);
}
else
pus h (*s);
s+ + ;
}
while (top! =- 1)
{
char opr = p o p ();
*t=o p r;
t+ + ;
}
*t='\0';
}
int infix::priority(ch a r c)
{
if (c= = ' ^ ' )
ret u r n 3;
if (c= = ' *' | | c = = ' / ' | | c = = ' % ' )
ret u r n 2;
50
else
{
if (c= = ' + ' | | c = = ' - ')
ret u r n 1;
else
ret u r n 0;
}
}
void main()
{
clrsc r();
char expr[MAX], *res[MAX];
infix q;
Ou t p u t :
Stack is empty
The prog r a m takes the input expre s sio n in postfix form. This
expre s sio n is scan n e d char a c t e r by char a c t e r . If the char a c t e r scan n e d
is an oper a n d , then first it is conve r t e d to a digit form and the n it is
pus h e d onto the stack. If the char a c t e r scan n e d is a blank spac e, then it
is skippe d. If the char a c t e r scan n e d is an oper a t o r , then the top two
elem e n t s from the stack are ret ri ev e d. An arith m e t i c oper a tio n is
perfor m e d betw e e n the two oper a n d s . The type of arith m e t i c oper a tio n
depe n d s on the oper a t o r scan n e d from the strin g s. The result is then
pus h e d back onto the stack. These step s are repe a t e d as long as the
strin g s is not exha u s t e d . Finally the value in the stack is the requir e d
result and is show n to the use r.
51
Pro g r a m :
#i n cl u d e <ios t r e a m . h >
#i n cl u d e <s t dlib.h >
#i n cl u d e <math.h >
#i n cl u d e <c ty p e. h >
#i n cl u d e <co nio. h >
class postfix
{
privat e:
int stack[MAX];
int top, n;
char *s;
public:
postfix();
void push(int item);
int pop();
void calcula t e( c h a r *str);
void show();
};
postfix::pos tfix()
{
top =- 1;
}
int postfix::pop()
{
if (top = = - 1)
{
cout < < e n d l < < " S t a c k is empty";
52
ret u r n NULL;
}
int data = s t a c k [ t o p];
top- -;
ret u r n dat a;
}
void postfix::calc ul a t e( c h a r *str)
{
s= s t r;
int n1, n2, n3;
while (*s)
{
if (*s = = ' '||*s = = ' \ t ')
{
s+ + ;
contin u e;
}
if (isdigit(*s))
{
n=*s- '0';
pus h(n);
}
else
{
n1 = p o p ();
n2 = p o p ();
switch(*s)
{
case '+':
n3 = n 2 + n 1 ;
bre a k;
case '-':
n3 = n 2- n1;
bre a k;
case '/':
n3 = n 2 / n 1 ;
bre a k;
case '*':
n3 = n 2* n 1;
bre a k;
case '%':
n3 = n 2 % n 1 ;
bre a k;
case ' ^ ':
n3 = p o w ( n 2 , n1);
bre a k;
default:
cout < < " U n k n o w n oper a t o r";
exit(1);
}
pus h(n 3);
53
}
s+ + ;
}
}
void postfix::s ho w()
{
n= p o p ();
cout < < " R e s u l t is: "< < n ;
}
void main()
{
clrsc r();
char expr[MAX];
cout < < "\nEnt e r postfix expr e s sio n to be evalua t e d : ";
cin > > e x p r ;
postfix q ;
q.calcul a t e ( e x p r);
q.sho w();
getch();
}
Ou t p u t :
Ente r postfix expr e s s io n to be evalua t e d : 53 ^ 5-
Result is: 120
QUEUE
The first elem e n t that gets adde d into the queu e is the first one to
get remov e d from the list. Henc e , que u e is also refe r r e d to as First- In-
First- Out list (FIFO). Queu e s can be repr e s e n t e d using both arr ays as
well as linked lists.
If que u e is imple m e n t e d using arr ays, the size of the array should
be fixed maxim u m allowing the que u e to expa n d or shrink.
Oper a t i o n s on a Qu e u e
54
addition of elem e n t s takes place. Initially, whe n the que u e is full, the
front and rea r is equal to -1.
Add(x)
An elem e n t can be add e d to the que u e only at the rea r end of the
queu e . Before addin g an elem e n t in the que u e, it is check e d whet h e r
queu e is full. If the que u e is full, the n addition canno t take place.
Othe r wi s e , the elem e n t is add e d to the end of the list at the rear side.
ADDQ(x )
If rear = MAX – 1
Then
Print “Queu e is full”
Retu r n
Else
Rear = rea r + 1
A[rea r] = x
If front = -1
Then
Front = 0
End if
End if
End ADDQ( )
Del( )
The del( ) oper a tio n delet e s the elem e n t from the front of the
queu e . Before deletin g and elem e n t , it is check e d if the que u e is empty.
If not the elem e n t point e d by front is delet e d from the queu e and front is
now mad e to point to the next elem e n t in the que u e .
DELQ( )
If front = -1
Then
Print “Queu e is Empty”
Retu r n
55
Else
Item = A[front]
A[front] = 0
If front = rea r
Then
Front = rea r = -1
Else
Front = front + 1
End if
Retu r n item
End if
End DELQ( )
Pro g r a m :
#i n cl u d e <ios t r e a m . h >
#i n cl u d e <co nio. h >
queu e:: q u e u e ()
{
front = r e a r = - 1;
}
56
{
if (front = = - 1)
{
cout < < " Q u e u e is empty!";
ret u r n NULL;
}
int item = a [f r o n t ];
a[fron t] = 0 ;
if (front = = r e a r )
front = r e a r = - 1;
else
front + + ;
ret u r n item;
}
void main()
{
clrsc r();
queu e q;
q.add q( 5 0);
q.add q( 4 0);
q.add q( 9 0);
q.dis play();
cout < < e n d l ;
int i=q.d el q();
cout < < e n d l ;
cout < < i < < " delet e d!";
cout < < e n d l ;
q.dis play();
i=q.d el q();
cout < < e n d l ;
cout < < i < < " delet e d!";
cout < < e n d l ;
i=q.d el q();
cout < < i < < " delet e d!";
cout < < e n d l ;
i=q.d el q();
getch();
}
Ou t p u t :
57
50 40 90
50 delet e d!
40 90
40 delet e d!
90 delet e d!
Queu e is empty!
58
Unit 3
LINKED LISTS
Linked lists and array s are simila r since they both stor e collection s of
dat a. One way to think abou t linked lists is to look at how arr ay s work
and think abou t alter n a t e app ro a c h e s .
Array is the most common data structure used to store collections of elements. Arrays are convenient
to declare and provide the easy syntax to access any element by its index number. Once the array is
set up, access to any element is convenient and fast.
The size of the arr ay is fixed. Most often this size is specified at
compile time. This make s the prog r a m m e r s to allocat e arr ays ,
which see m s "larg e enou g h" than requi r e d .
Linked lists have their own strengths and weaknesses, but they happen to be strong where arrays are
weak. Generally array's allocates the memory for all its elements in one block whereas linked lists use
an entirely different strategy.
Linked lists allocat e mem o ry for each elem e n t sep a r a t e ly and only when
nec es s a r y.
Her e is a quick review of the ter mi nology and rules of point e r s . The
linked list code will dep e n d on the following functions :
Since a void * is returned the C standard states that this pointer can be converted to any type. For
example,
char *cp;
cp = (char *) malloc (100);
Attempts to get 100 bytes and assigns the starting address to cp. We can also use the sizeof()
function to specify the number of bytes. For example,
int *ip;
ip = (int *) malloc (100*sizeof(int));
59
free() is the opposite of malloc(), which de-allocates memory. The argument to free() is a pointer to a
block of memory in the heap — a pointer which was obtained by a malloc() function. The syntax is:
free (ptr);
The advantage of free() is simply memory management when we no longer need a block.
6. 1. Link e d List:
A linked list is a non-sequential collection of data items. It is a dynamic data structure. For every data
item in a linked list, there is an associated pointer that would give the memory location of the next
data item in the linked list.
The data items in the linked list are not in consecutive memory locations. They may be anywhere, but
the accessing of these data items is easier as each data item contains the address of the next data
item.
1. Linked lists are dyna mic dat a struc t u r e s . i.e., they can grow or
shrink durin g the executio n of a prog r a m .
3. Inse r tio n and Deletion s are easie r and efficient. Linked lists
provide flexibility in inse rtin g a dat a item at a specified position
and deletion of the dat a item from the given position.
4. Many complex applica tio n s can be easily carri e d out with linked
lists.
Basically we can put linked lists into the following four item s:
60
3. Circul a r Linke d List.
4. Circul a r Double Linked List.
A single linked list is one in which all node s are linked toget h e r in som e
sequ e n ti al man n e r. Henc e, it is also called as linea r linked list.
A doubl e linked list is one in which all node s are linked toget h e r by
multiple links which helps in acce s si n g both the succ e s s o r node (next
node) and pred e c e s s o r node (previous node) from any arbit r a r y node
within the list. Ther efo r e eac h node in a double linked list has two link
fields (point e r s ) to point to the left node (previou s) and the right node
(next). This helps to trave r s e in forwa r d direc tio n and backw a r d
direc tio n.
A circula r linke d list is one, which has no beginni n g and no end. A single
linked list can be mad e a circul a r linked list by simply storin g add r e s s of
the very first node in the link field of the last node.
A circula r double linked list is one, which has both the succ e s s o r point e r
and pred e c e s s o r pointe r in the circula r man n e r .
P(x) = a 0 Xn + a 1 Xn- 1 + …… + a n- 1 X + a n
61
2. Repr e s e n t very larg e num b e r s and oper a tio n s of the larg e num b e r
such as addition, multiplica tio n and division.
A linked list allocates space for each element separately in its own block of memory called a "node".
The list gets an overall structure by using pointers to connect all its nodes together like the links in a
chain.
Each node cont ai n s two fields; a "dat a" field to stor e what ev e r elem e n t ,
and a "next" field which is a point e r used to link to the next node.
Each node is alloca t e d in the hea p using malloc(), so the node mem o ry
contin u e s to exist until it is explicitly de- allocat e d using free(). The front
of the list is a point e r to the “star t ” node. A single linked list is show n in
figure 6.2.1.
S TAC K H EAP
100
st a rt
10 200 20 300 30 400 40 X
T h e st art 100 200 300 400
p o int er
h o ld s t h e Ea c h n o d e St o r e s t h e n e xt T h e n e xt f i e l d of
a d dr e s s of st or e s t h e d at a. n o d e a d dr e s s. t h e l a st n o d e i s
t h e f ir s t N ULL.
n o d e of t h e
l i st .
Fi g u r e 6 . 2 . 1 . S i n g l e L i n k e d L i s t
The beginni n g of the linked list is store d in a " start " point e r which points
to the first node. The first node cont ai n s a point e r to the secon d node.
The secon d node cont ai n s a point e r to the third node, ... and so on. The
last node in the list has its next field set to NULL to mark the end of the
list. Code can acce s s any node in the list by sta rti n g at the start and
following the next point e r s .
62
Before writing the code to build the above list, we nee d to crea t e a start
node , used to crea t e and acce s s othe r node s in the linked list. The
following struc t u r e definition will do (see figur e 6.2.2):
st r u ct s l i n k l ist
{
int d at a; node: d at a n e xt
st r u ct s l i n k l ist * n e x t ;
};
t y p e d e f st r u ct s l i n k l ist n o d e ; st a rt
n o d e * st a r t = N U L L; E m p t y li s t : NULL
Fi g u r e 6 . 2 . 2 . S t r u c t u r e d e f i n it i o n , s i n g l e l i n k n o d e a n d e m p t y l i s t
Crea tio n.
Inse r tio n.
Deletion.
Traver si n g.
Creating a singly linked list starts with creating a node. Sufficient memory has to be allocated for
creating a node. The information is stored in the memory, allocated by using the malloc() function.
The function getnode(), is used for creating a node, after allocating memory for the structure of type
node, the information for the item (i.e., data) has to be read from the user, set next field to NULL and
finally returns the address of the node. Figure 6.2.3 illustrates the creation of a node for single linked
list.
no d e* g et no d e( )
{ new node
no d e* n e w no d e;
n e w n o d e = ( n o d e * ) m a l l o c ( s iz e o f ( n o d e ) ) ; 10 X
p r i n t f ( " \ n En t e r d a t a : " ) ; 100
s ca n f ( " % d " , & n e w n o d e - > d a t a ) ;
n e w n o d e - > n e x t = N U L L;
r et u r n n e w no d e;
}
Fi g u r e 6 . 2 . 3 . n e w n o d e w it h a v a l u e o f 1 0
63
Get the new node using get no d e ().
start = newnode;
If the list is not empty, follow the steps given below:
The next field of the new node is mad e to point the first
node (i.e. sta rt node) in the list by assignin g the addr e s s of
the first node.
st a rt
100
Fi g u r e 6 . 2 . 4 . S i n g l e L i n k e d L i s t w it h 4 n o d e s
The function cre a t elis t(), is used to cre a t e ‘n’ num b e r of node s:
v o i d c r e a t e list ( i n t n )
{
i n t i;
no d e * n e w no d e;
no d e * t e m p ;
fo r( i = 0 ; i < n ; i+ + )
{
n e w no d e = g et no d e( ) ;
if ( st a r t = = N U L L)
{
st a rt = n e w no d e;
}
e ls e
{
t e m p = st a r t ;
w h i l e ( t e m p - > n e x t ! = N U L L)
tem p = t em p - > next;
t e m p - > n e x t = n e w no d e;
}
}
}
64
Ins e r t i o n of a Nod e :
One of the most primitive operations that can be done in a singly linked list is the insertion of a node.
Memory is to be allocated for the new node (in a similar way that is done while creating a list) before
reading the data. The new node will contain empty data field and empty next field. The data field of
the new node is then stored with the information read from the user. The next field of the new node is
assigned to NULL. The new node can then be inserted at three different places namely:
Ins e r t i n g a nod e at th e be g i n n i n g :
The function inser t_at_b e g(), is used for insertin g a node at the
beginni n g
Figur e 6.2.5 shows inser ti n g a node into the single linked list at the
beginni n g.
65
st a rt
500
5 100
500
Fi g u r e 6 . 2 . 5 . I n s e r t i n g a n o d e a t t h e b e g i n n i n g
Ins e r t i n g a nod e at th e en d:
The following steps are followe d to inse r t a new node at the end of the
list:
newnode = getnode();
tem p = start;
while(te m p -> next != NULL)
tem p = tem p -> next;
temp -> next = newnode;
The function inser t_at_e n d(), is use d for inser ti n g a node at the end.
Figur e 6.2.6 shows inse r ti n g a node into the single linked list at the end.
st a rt
100
50 X
500
Fi g u r e 6 . 2 . 6 . I n s e r t i n g a n o d e a t t h e e n d .
The following steps are followed, to insert a new node in an intermediate position in the list:
66
Ens u r e that the specified position is in betw e e n first node and
last node. If not, specified position is invalid. This is done by
count n o d e () function.
The function inser t_at_mi d(), is used for inser ti n g a node in the
inter m e d i a t e position.
Figure 6.2.7 shows inserting a node into the single linked list at a specified intermediate position other
than beginning and end.
st a rt pr ev t e mp
100
50 300
500 new node
Fi g u r e 6 . 2 . 7 . I n s e r t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n .
Del e t i o n of a nod e:
Anothe r primitive oper a tio n that can be done in a singly linked list is the
deletion of a node. Memo ry is to be rele a s e d for the node to be delet e d. A
node can be delet e d from the list from thre e differe n t place s nam ely.
Del e t i n g a nod e at th e be g i n n i n g :
67
The following steps are followe d, to delet e a node at the beginni n g of the
list:
tem p = start;
star t = star t -> next;
free(t e m p );
The function delete_at_beg(), is used for deleting the first node in the list.
Figure 6.2.8 shows deleting a node at the beginning of a single linked list.
st a rt
200
Fi g ur e 6. 2. 8. De l e t i n g a n o d e at t h e b e g i n n i n g.
Del e t i n g a nod e at th e en d:
The following steps are followe d to delet e a node at the end of the list:
The function delet e_a t_las t(), is used for deletin g the last node in the list.
Figur e 6.2.9 shows deletin g a node at the end of a single linked list.
68
st a rt
100
10 200 20 300 30 X 40 X
100 200 300 400
Fi g u r e 6 . 2 . 9 . D e l e t i n g a n o d e a t t h e e n d .
Figure 6.2.10 shows deleting a node at a specified intermediate position other than beginning and
end from a single linked list.
st a rt
100
Fi g u r e 6 . 2 . 1 0 . De l e t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n .
69
To display the inform a tio n, you have to trave r s e (move) a linked list,
node by node from the first node, until the end of the list is reac h e d .
Traver si n g a list involves the following steps:
v o id t r a v e rs e( )
{
no d e * t e m p ;
t e m p = st a r t ;
p r i n t f ( " \ n T h e co n t e n t s o f L ist ( L e f t t o Ri g h t ) : \ n " ) ;
if ( st a r t = = N U L L )
p r i n t f ( " \ n Em p t y L ist " ) ;
e ls e
w h i l e ( t e m p ! = N U L L)
{
p r int f( " % d - > " , t e m p - > d at a) ;
tem p = t em p - > next;
}
p r i n t f ( " X" ) ;
}
v o i d r e v _ t r a v e r s e ( n o d e * st )
{
if ( st = = N U L L)
{
r et u r n;
}
e ls e
{
r e v _ t r a v e r s e ( st - > n e x t ) ;
p r i n t f ( " % d - > " , st - > d a t a ) ;
}
}
Cou n t i n g th e Nu m b e r of Nod e s :
The following code will count the num b e r of node s exist in the list using
recursio n .
70
i n t co u n t n o d e ( n o d e * st )
{
if ( st = = N U L L)
r et u r n 0 ;
e ls e
r e t u r n ( 1 + co u n t n o d e ( st - > n e x t ) ) ;
}
6.3. A Complete Source Code for the Implementation of Single Linked List:
stru ct slinklist
{
int data;
stru ct slinklist *next;
};
int menu()
{
int ch;
clrscr();
printf("\n 1.Cre a t e a list ");
printf("\n- -------------------------");
printf("\n 2.Inse r t a node at beginnin g ");
printf("\n 3.Inse r t a node at end");
printf("\n 4.Inse r t a node at middle");
printf("\n- -------------------------");
printf("\n 5.Delet e a node from begin nin g");
printf("\n 6.Delet e a node from Last");
printf("\n 7.Delet e a node from Middle");
printf("\n- -------------------------");
printf("\n 8.Trave r s e the list (Left to Right)");
printf("\n 9.Trave r s e the list (Right to Left)");
printf("\n- -------------------------");
printf("\n 10. Count node s ");
printf("\n 11. Exit ");
printf("\n\n Enter your choice: ");
scanf("%d",&ch);
retu r n ch;
}
71
}
retu r n (count);
}
72
star t = newno d e;
}
}
void insert_at_mid()
{
node *newnod e, *temp, *prev;
int pos, nodec t r , ctr = 1;
newno d e = getno d e();
printf("\n Ente r the position: ");
scanf("%d", &pos);
nodect r = count n o d e ( s t a r t );
if(pos > 1 && pos < nodect r)
{
tem p = prev = start;
while(ctr < pos)
{
prev = tem p;
tem p = temp -> next;
ctr + + ;
}
prev -> next = newno d e ;
newno d e -> next = tem p;
}
else
{
printf("position %d is not a middle position", pos);
}
}
73
printf("\n Empty List..");
retu r n ;
}
else
{
tem p = start;
prev = star t;
while(te m p -> next != NULL)
{
prev = tem p;
tem p = temp -> next;
}
prev -> next = NULL;
free(t e m p );
printf("\n Node delet e d ");
}
}
}
if(pos > 1 && pos < nodect r)
{
tem p = prev = start;
while(ctr < pos)
{
prev = tem p;
tem p = temp -> next;
ctr + + ;
}
prev -> next = tem p -> next;
free(t e m p );
printf("\n Node delet e d ..");
}
else
{
printf("\n Invalid position..");
getch();
}
}
}
void main(void)
{
int ch, n;
clrscr();
while(1)
{
ch = men u();
switch(c h)
{
case 1:
74
if(star t = = NULL)
{
printf("\n Num b e r of nodes you want to crea t e : ");
scanf("%d", &n);
creat elist(n);
printf("\n List crea t e d . .");
}
else
printf("\n List is alre a dy cre at e d . .");
brea k;
case 2:
insert_at_be g();
brea k;
case 3:
insert_at_en d();
brea k;
case 4:
insert_at_mid();
brea k;
case 5:
delet e_at_be g();
brea k;
case 6:
delet e_at_las t();
brea k;
case 7:
delet e_at_mid();
brea k;
case 8:
trave r s e();
brea k;
case 9:
printf("\n The conte n t s of List (Right to Left): \n");
rev_tr av e r s e ( s t a r t );
printf(" X ");
brea k;
case 10:
printf("\n No of nodes : %d ", count no d e( s t a r t ));
brea k;
case 11 :
exit(0);
}
getch();
}
}
A double linked list is a two-way list in which all nodes will have two links. This helps in accessing
both successor node and predecessor node from the given node position. It provides bi-directional
traversing. Each node contains three fields:
Left link.
Data.
Right link.
The left link point s to the pred e c e s s o r node and the right link points to
the succ e s s o r node. The data field store s the requir e d dat a.
Many applica tion s requir e sea rc hi n g forwa r d and backw a r d thru node s
of a list. For exam pl e sea rc hi n g for a nam e in a telep h o n e direct o ry
75
would nee d forw a r d and backw a r d scan ni n g thru a region of the whole
list.
Crea tio n.
Inse r tio n.
Deletion.
Traver si n g.
S TAC K St o r e s t h e H EAP
pr ev io u s n o d e
100 a d dr e s s.
st a rt
X 10 200 100 20 300 200 30 X
T h e st art 100 200 300
p o int er
h o ld s t h e St o r e s t h e d a t a . St o r e s t h e n e xt Th e r ig ht f ie ld of
a d dr e s s of n o d e a d dr e s s. t h e l a st n o d e i s
t h e f ir s t N ULL.
n o d e of t h e
l i st .
Fi g u r e 6 . 3 . 1 . D o u b l e L i n k e d L i s t
The begin ni n g of the double linked list is store d in a " start " point e r
which points to the first node. The first node’s left link and last node’s
right link is set to NULL.
st r u ct d l i n k l ist
{ node: lef t d at a r ig ht
st r u ct d l i n k l ist * l e f t ;
int d at a;
st r u ct d l i n k l ist * r i g h t ;
}; st a rt
E m p t y li s t : NULL
t y p e d e f st r u ct d l i n k l ist n o d e ;
n o d e * st a r t = N U L L;
Fi g u r e 6 . 4 . 1 . S t r u c t u r e d e f i n it i o n , d o u b l e l i n k n o d e a n d e m p t y l i s t
76
no d e* g et no d e( )
{
no d e* n e w no d e;
n e w n o d e = ( n o d e * ) m a l l o c( s iz e o f ( n o d e ) ) ; new node
p r in t f ( " \ n En t e r d a t a : " ) ; X 10 X
sca n f ( " % d " , & n e w n o d e - > d a t a ) ;
n e w n o d e - > l e f t = N U L L; 100
n e w n o d e - > r i g h t = N U L L;
r et u r n n e w no d e;
}
Fi g u r e 6 . 4 . 2 . n e w n o d e w it h a v a l u e o f 1 0
new no d e = g e t n o d e ();
The function cre a t elis t(), is used to cre a t e ‘n’ num b e r of node s:
v o i d c r e a t e list ( i n t n )
{
i n t i;
no d e * n e w no d e;
no d e * t e m p ;
fo r( i = 0 ; i < n; i+ + )
{
n e w no d e = g et no d e( ) ;
if ( st a r t = = N U L L)
{
st a r t = n e w n o d e ;
}
e ls e
{
t e m p = st a r t ;
w h ile( t e m p - > r ig ht )
t e m p = t e m p - > r ig ht ;
t e m p - > r ig ht = n e w no d e;
n e w no d e - > left = t e m p ;
}
}
}
77
Figur e 6.4.3 shows 3 item s in a double linked list stor e d at differ e n t
locations.
st a rt
100
Fi g u r e 6 . 4 . 3 . D o u b l e L i n k e d L i s t w it h 3 n o d e s
Ins e r t i n g a nod e at th e be g i n n i n g :
new no d e = g e t n o d e ( );
The function dbl_ins e r t_b e g(), is use d for inser ti n g a node at the
beginni n g. Figur e 6.4.4 shows inser ti n g a node into the double linked list
at the begin ni n g.
st a rt
400
X 40 100
400
Fi g u r e 6 . 4 . 4 . I n s e r t i n g a n o d e a t t h e b e g i n n i n g
Ins e r t i n g a nod e at th e en d:
The following steps are followe d to inse r t a new node at the end of the
list:
78
newnode=getnode();
tem p = start;
while(te m p -> right != NULL)
tem p = tem p -> right;
tem p -> right = new no d e ;
new no d e -> left = temp;
The function dbl_ins e r t_e n d (), is used for inse rti n g a node at the end.
Figur e 6.4.5 shows inse r ti n g a node into the double linked list at the end.
st a rt
100
300 40 X
400
Fi g u r e 6 . 4 . 5 . I n s e r t i n g a n o d e a t t h e e n d
new no d e = g e t n o d e ( );
79
The function dbl_ins e r t_ mi d(), is used for inser ti n g a node in the
inter m e d i a t e position. Figur e 6.4.6 shows inser ti n g a node into the
double linke d list at a specifie d inter m e d i a t e position othe r than
beginni n g and end.
st a rt
100 40 200
100
400
400 20 300
X 10 400
200
100
200 30 X
300
Fi g u r e 6 . 4 . 6 . I n s e r t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n
Del e t i n g a nod e at th e be g i n n i n g :
The following steps are followe d, to delet e a node at the beginni n g of the
list:
tem p = start;
star t = star t -> right;
star t -> left = NULL;
free(t e m p );
The function dbl_delet e_b e g(), is used for deletin g the first node in the
list. Figur e 6.4.6 shows deletin g a node at the begin ni n g of a doubl e
linked list.
st a rt
200
Fi g u r e 6 . 4 . 6 . D e l e t i n g a n o d e a t b e g i n n i n g
Del e t i n g a nod e at th e en d:
The following steps are followe d to delet e a node at the end of the list:
If list is empty then display ‘Empty List’ mess a g e
tem p = start;
80
while(te m p -> right != NULL)
{
tem p = tem p -> right;
}
tem p -> left -> right = NULL;
free(t e m p );
The function dbl_delet e_la s t(), is use d for deletin g the last node in the
list. Figur e 6.4.7 shows deletin g a node at the end of a double linked list.
st a rt
100
Fi g u r e 6 . 4 . 7 . D e l e t i n g a n o d e a t t h e e n d
81
The function delete_at_mid(), is used for deleting the intermediate node in the list. Figure 6.4.8 shows
deleting a node at a specified intermediate position other than beginning and end from a double
linked list.
st a rt
100
Fi g u r e 6 . 4 . 8 D e l e t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n
To display the inform a ti o n, you have to trave r s e the list, node by node
from the first node, until the end of the list is reac h e d . The function
traver s e_left_righ t () is used for trave r si n g and displaying the inform a ti o n
stor e d in the list from left to right.
The following steps are followe d, to trave r s e a list from left to right:
tem p = start;
while(te m p != NULL)
{
print tem p -> data;
tem p = tem p -> right;
}
To display the inform a tio n from right to left, you have to trave r s e the list,
node by node from the first node, until the end of the list is reac h e d . The
function travers e_rig h t_lef t () is used for trave r si n g and displayin g the
inform a tio n store d in the list from right to left.
The following steps are followe d, to trave r s e a list from right to left:
tem p = start;
while(te m p -> right != NULL)
tem p = tem p -> right;
while(te m p != NULL)
82
{
print tem p -> data;
tem p = tem p -> left;
}
Cou n t i n g th e Nu m b e r of Nod e s :
The following code will count the num b e r of node s exist in the list (using
rec u r sio n).
i n t co u n t n o d e ( n o d e * st a r t )
{
if ( st a r t = = N U L L)
r et u r n 0 ;
e ls e
r e t u r n ( 1 + co u n t n o d e ( st a r t - > r i g h t ) ) ;
}
6.5. A Complete Source Code for the Implementation of Double Linked List:
stru ct dlinklist
{
stru ct dlinklist *left;
int data;
stru ct dlinklist *right;
};
83
retu r n 0;
else
retu r n 1 + count n o d e ( s t a r t -> right);
}
int menu()
{
int ch;
clrscr();
printf("\n 1.Cre a t e ");
printf("\n- -----------------------------");
printf("\n 2. Inser t a node at begin nin g ");
printf("\n 3. Inser t a node at end");
printf("\n 4. Inser t a node at middle");
printf("\n- -----------------------------");
printf("\n 5. Delete a node from beginni n g");
printf("\n 6. Delete a node from Last");
printf("\n 7. Delete a node from Middle");
printf("\n- -----------------------------");
printf("\n 8. Traver s e the list from Left to Right ");
printf("\n 9. Traver s e the list from Right to Left ");
printf("\n- -----------------------------");
printf("\n 10.Cou n t the Num b e r of node s in the list");
printf("\n 11.Exit ");
printf("\n\n Enter your choice: ");
scanf("%d", &ch);
retu r n ch;
}
84
node *temp;
tem p = start;
printf("\n The conte n t s of List: ");
if(star t = = NULL)
printf("\n Empty List");
else
while(te m p -> right != NULL)
tem p = temp -> right;
while(te m p != NULL)
{
printf("\t%d", temp -> data);
tem p = temp -> left;
}
}
85
tem p -> right = newno d e ;
}
else
printf("position %d of list is not a middle position ", pos);
}
86
while(i < pos)
{
tem p = temp -> right;
i+ + ;
}
tem p -> right -> left = temp -> left;
tem p -> left -> right = temp -> right;
free(t e m p );
printf("\n node delet e d ..");
}
else
{
printf("\n It is not a middle position..");
getch();
}
}
}
void main(void)
{
int ch, n;
clrscr();
while(1)
{
ch = men u();
switch( ch)
{
case 1 :
printf("\n Ente r Numb e r of nodes to creat e: ");
scanf("%d", &n);
creat elist(n);
printf("\n List crea t e d . .");
brea k;
case 2 :
dll_inser t_b e g();
brea k;
case 3 :
dll_inser t_en d ();
brea k;
case 4 :
dll_inser t_mid();
brea k;
case 5 :
dll_delet e_b e g();
brea k;
case 6 :
dll_delet e_last();
brea k;
case 7 :
dll_delet e_mi d();
brea k;
case 8 :
trave r s e_left_to_righ t();
brea k;
case 9 :
trave r s e_rig h t_to_left();
brea k;
case 10 :
printf("\n Num b e r of nodes: %d", count n o d e( s t a r t ));
brea k;
case 11:
exit(0);
}
getch();
}
}
87
6. 6. Circ u l a r Sin g l e Link e d List:
It is just a single linke d list in which the link field of the last node points
back to the add r e s s of the first node. A circula r linke d list has no
beginni n g and no end. It is nece s s a r y to esta blis h a special point e r called
start point e r always pointin g to the first node of the list. Circula r linked
lists are frequ e n tly use d inste a d of ordina ry linke d list beca u s e many
oper a tio n s are much easie r to imple m e n t . In circul a r linked list no null
point e r s are used, henc e all point e r s cont ai n valid addr e s s .
st a rt
100
Fi g u r e 6 . 6 . 1 . C ir c u l a r S i n g l e L i n k e d L i s t
Crea tio n.
Inse r tio n.
Deletion.
Traver si n g.
start = newnode;
tem p = start;
while(te m p -> next != NULL)
tem p = tem p -> next;
tem p -> next = newno d e ;
88
new no d e -> next = star t;
The function cre a t elis t(), is used to cre a t e ‘n’ num b e r of node s:
Ins e r t i n g a nod e at th e be g i n n i n g :
star t = new no d e ;
new no d e -> next = star t;
last = star t;
while(las t -> next != sta rt)
last = last -> next;
new no d e -> next = star t;
star t = new no d e ;
last -> next = start;
The function cll_inse r t_b e g(), is used for inser ti n g a node at the
beginni n g. Figur e 6.6.2 show s inser ti n g a node into the circula r single
linked list at the begin ni n g.
st a rt
500
5 100
500
Fi g u r e 6 . 6 . 2 . I n s e r t i n g a n o d e a t t h e b e g i n n i n g
Ins e r t i n g a nod e at th e en d:
The following steps are followe d to inse r t a new node at the end of the
list:
89
If the list is empty, assign new node as start.
star t = new no d e ;
new no d e -> next = star t;
The function cll_inse r t_e n d (), is used for inser ti n g a node at the end.
Figur e 6.6.3 shows inser ti n g a node into the circula r single linked list at
the end.
st a rt
100
50 100
500
Fi g u r e 6 . 6 . 3 I n s e r t i n g a n o d e a t t h e e n d .
Del e t i n g a nod e at th e be g i n n i n g :
The following steps are followe d, to delet e a node at the beginni n g of the
list:
After deletin g the node, if the list is empty the n start = NULL.
The function cll_delet e_b e g (), is used for deletin g the first node in the
list. Figur e 6.6.4 shows deletin g a node at the begin ni n g of a circul a r
90
single linked list.
st a rt
200
Fi g u r e 6 . 6 . 4 . D e l e t i n g a n o d e a t b e g i n n i n g .
Del e t i n g a nod e at th e en d:
The following steps are followe d to delet e a node at the end of the list:
tem p = start;
prev = star t;
while(te m p -> next != star t)
{
prev = temp;
tem p = tem p -> next;
}
prev -> next = start;
After deletin g the node, if the list is empty the n start = NULL.
The function cll_delet e_la s t(), is used for deletin g the last node in the
list.
Figur e 6.6.5 shows deletin g a node at the end of a circula r single linked
list.
st a rt
100
Fi g u r e 6 . 6 . 5 . D e l e t i n g a n o d e a t t h e e n d .
The following steps are followe d, to trave r s e a list from left to right:
91
If the list is not empty, follow the step s given below:
tem p = start;
do
{
printf("%d ", temp -> data);
tem p = tem p -> next;
} while(t e m p != sta rt);
stru ct cslinklist
{
int data;
stru ct cslinklist *next;
};
int menu()
{
int ch;
clrscr();
printf("\n 1. Crea t e a list ");
printf("\n\n- -------------------------");
printf("\n 2. Inser t a node at begin nin g ");
printf("\n 3. Inser t a node at end");
printf("\n 4. Inser t a node at middle");
printf("\n\n- -------------------------");
printf("\n 5. Delete a node from beginni n g");
printf("\n 6. Delete a node from Last");
printf("\n 7. Delete a node from Middle");
printf("\n\n- -------------------------");
printf("\n 8. Display the list");
printf("\n 9. Exit");
printf("\n\n- -------------------------");
printf("\n Ente r your choice: ");
scanf("%d", &ch);
retu r n ch;
92
}
void display()
{
node *temp;
tem p = start;
printf("\n The conte n t s of List (Left to Right): ");
if(star t = = NULL )
printf("\n Empty List");
else
do
{
printf("\t %d ", temp -> data);
tem p = temp -> next;
}while(te m p != start);
printf(" X ");
}
93
{
star t = newno d e;
newno d e -> next = start;
}
else
{
tem p = start;
while(te m p -> next != start)
tem p = temp -> next;
tem p -> next = newno d e ;
newno d e -> next = start;
}
printf("\n Node insert e d at end..");
nodect r + + ;
}
94
void cll_delet e_last()
{
node *temp,*pr ev;
if(star t = = NULL)
{
printf("\n No nodes exist..");
getch();
retu r n ;
}
else
{
tem p = start;
prev = star t;
while(te m p -> next != start)
{
prev = tem p;
tem p = temp -> next;
}
prev -> next = star t;
free(t e m p );
nodect r- -;
if(nodec t r = = 0)
star t = NULL;
printf("\n Node delet e d ..");
}
}
if(star t = = NULL)
{
printf("\n No nodes exist..");
getch();
retu r n ;
}
else
{
printf("\n Which node to delete: ");
scanf("%d", &pos);
if(pos > nodec t r)
{
printf("\nThis node does not exist");
getch();
retu r n ;
}
if(pos > 1 && pos < nodect r)
{
tem p = s t a r t ;
prev = star t;
i = 0;
while(i < pos - 1)
{
prev = tem p;
tem p = temp -> next ;
i+ + ;
}
prev -> next = tem p -> next;
free(t e m p );
nodect r- -;
printf("\n Node Delete d..");
}
else
{
printf("\n It is not a middle position..");
getch();
95
}
}
}
void main(void)
{
int result;
int ch, n;
clrscr();
while(1)
{
ch = men u();
switch(c h)
{
case 1 :
if(star t = = NULL)
{
printf("\n Ente r Numb e r of nodes to creat e: ");
scanf("%d", &n);
creat elist(n);
printf("\nList creat e d ..");
}
else
printf("\n List is alre a dy Exist..");
brea k;
case 2 :
cll_inser t_b e g();
brea k;
case 3 :
cll_inser t_e n d();
brea k;
case 4 :
cll_inser t_mid();
brea k;
case 5 :
cll_delet e_b e g();
brea k;
case 6 :
cll_delet e_last();
brea k;
case 7 :
cll_delet e_ mid();
brea k;
case 8 :
display();
brea k;
case 9 :
exit(0);
}
getch();
}
}
A circula r double linke d list has both succ e s s o r point e r and pred e c e s s o r
point e r in circul a r man n e r . The objective behin d consid e ri n g circula r
double linke d list is to simplify the inser tion and deletion oper a tio n s
perfor m e d on doubl e linked list. In circula r double linked list the right
link of the right most node points back to the start node and left link of
the first node points to the last node.
96
A circula r double linke d list is show n in figur e 6.8.1.
100
st a rt
300 10 200 100 20 300 200 30 100
Fi g u r e 6 . 8 . 1 . C ir c u l a r D o u b l e L i n k e d L i s t
Crea tio n.
Inse r tio n.
Deletion.
Traver si n g.
star t = new no d e ;
new no d e -> left = star t;
new no d e -> ri g h t = start;
The function cdll_cre a t e lis t(), is use d to cre a t e ‘n’ num b e r of node s:
Ins e r t i n g a nod e at th e be g i n n i n g :
97
new no d e = g e t n o d e ( );
star t = new no d e ;
new no d e -> left = star t;
new no d e -> right = start;
The function cdll_ins e r t_b e g (), is used for inse r ti n g a node at the
beginni n g. Figur e 6.8.2 show s inser ti n g a node into the circula r doubl e
linked list at the begin ni n g.
st a rt
400
300 40 100
400
Fi g u r e 6 . 8 . 2 . I n s e r t i n g a n o d e a t t h e b e g i n n i n g
Ins e r t i n g a nod e at th e en d:
The following steps are followe d to inse r t a new node at the end of the
list:
newnode=getnode();
star t = new no d e ;
new no d e -> left = star t;
new no d e -> right = start;
98
The function cdll_ins e r t_e n d(), is used for inser ti n g a node at the end.
Figur e 6.8.3 shows inser ti n g a node into the circula r linke d list at the
end.
st a rt
100
300 40 100
400
Fi g u r e 6 . 8 . 3 . I n s e r t i n g a n o d e a t t h e e n d
new no d e = g e t n o d e ( );
The function cdll_insert_mid(), is used for inserting a node in the intermediate position. Figure 6.8.4
shows inserting a node into the circular double linked list at a specified intermediate position other
than beginning and end.
99
st a rt
100 40 200
100
400
300 10 400 400 20 300
100 200
200 30 100
300
Fi g u r e 6 . 8 . 4 . I n s e r t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n
Del e t i n g a nod e at th e be g i n n i n g :
The following steps are followe d, to delet e a node at the beginni n g of the
list:
tem p = start;
star t = star t -> right;
tem p -> left -> right = star t;
star t -> left = tem p -> left;
The function cdll_delet e_b e g (), is used for deletin g the first node in the
list. Figur e 6.8.5 shows deletin g a node at the begin ni n g of a circul a r
double linke d list.
st a rt
200
Fi g u r e 6 . 8 . 5 . D e l e t i n g a n o d e a t b e g i n n i n g
Del e t i n g a nod e at th e en d:
The following steps are followe d to delet e a node at the end of the list:
100
tem p = start;
while(te m p -> right != star t)
{
tem p = tem p -> right;
}
tem p -> left -> right = tem p -> right;
tem p -> right -> left = tem p -> left;
The function cdll_delet e_la s t(), is used for deletin g the last node in the
list. Figur e 6.8.6 shows deletin g a node at the end of a circul a r double
linked list.
st a rt
100
Fi g u r e 6 . 8 . 6 . D e l e t i n g a n o d e a t t h e e n d
tem p = start;
i = 1;
while(i < pos)
{
tem p = tem p -> right ;
i+ + ;
}
tem p -> right -> left = tem p -> left;
tem p -> left -> right = tem p -> right;
free(t e m p );
101
printf("\n node delet e d..");
nodec t r- -;
}
The function cdll_delet e_ mid(), is used for deletin g the inter m e d i a t e node
in the list.
Figure 6.8.7 shows deleting a node at a specified intermediate position other than beginning and end
from a circular double linked list.
st a rt
100
Fi g u r e 6 . 8 . 7 . D e l e t i n g a n o d e a t a n i n t e r m e d i a t e p o s it i o n
The following steps are followe d, to trave r s e a list from left to right:
tem p = start;
Print tem p -> dat a;
tem p = tem p -> right;
while(te m p != star t)
{
print tem p -> data;
tem p = tem p -> right;
}
The following steps are followe d, to trave r s e a list from right to left:
102
tem p = tem p -> left;
print tem p -> data;
} while(t e m p != sta rt);
stru ct cdlinklist
{
stru ct cdlinklist *left;
int data;
stru ct cdlinklist *right;
};
int menu()
{
int ch;
clrscr();
printf("\n 1. Crea t e ");
printf("\n\n- -------------------------");
printf("\n 2. Inser t a node at Beginnin g");
printf("\n 3. Inser t a node at End");
printf("\n 4. Inser t a node at Middle");
printf("\n\n- -------------------------");
printf("\n 5. Delete a node from Beginni n g");
printf("\n 6. Delete a node from End");
printf("\n 7. Delete a node from Middle");
printf("\n\n- -------------------------");
printf("\n 8. Display the list from Left to Right");
printf("\n 9. Display the list from Right to Left");
printf("\n 10.Exit");
printf("\n\n Enter your choice: ");
scanf("%d", &ch);
retu r n ch;
}
103
{
nodect r = n;
for(i = 0; i < n; i+ + )
{
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
newno d e -> left = star t;
newno d e -> rig h t = start;
}
else
{
newno d e -> left = start -> left;
newno d e -> right = star t;
star t -> left- > rig h t = newno d e;
star t -> left = newno d e ;
}
}
}
else
{
printf("\n List alrea dy exists..");
}
}
104
star t = newno d e;
newno d e -> left = star t;
newno d e -> right = star t;
}
else
{
newno d e -> left = star t -> left;
newno d e -> right = star t;
star t -> left -> right = newno d e;
star t -> left = newno d e ;
star t = newno d e;
}
}
}
}
105
void cdll_delet e_b e g()
{
node *temp;
if(star t = = NULL)
{
printf("\n No nodes exist..");
getch();
retu r n ;
}
else
{
nodect r- -;
if(nodec t r = = 0)
{
free(st a r t );
star t = NULL;
}
else
{
tem p = start;
star t = start -> right;
tem p -> left -> right = start;
star t -> left = tem p -> left;
free(t e m p );
}
printf("\n Node delet e d at Beginnin g..");
}
}
106
else
{
printf("\n Which node to delete: ");
scanf("%d", &pos);
if(pos > nodec t r)
{
printf("\nThis node does not exist");
getch();
retu r n ;
}
if(pos > 1 && pos < nodect r)
{
tem p = start;
while(ctr < pos)
{
tem p = temp -> right ;
ctr + + ;
}
tem p -> right -> left = temp -> left;
tem p -> left -> right = temp -> right;
free(t e m p );
printf("\n node delet e d ..");
nodect r- -;
}
else
{
printf("\n It is not a middle position..");
getch();
}
}
}
void main(void)
{
int ch,n;
clrscr();
while(1)
{
ch = men u();
switch( ch)
{
case 1 :
printf("\n Ente r Numb e r of nodes to creat e: ");
scanf("%d", &n);
cdll_cre a t elist( n);
printf("\n List crea t e d . .");
brea k;
case 2 :
cdll_inser t_b e g ();
brea k;
case 3 :
cdll_inser t_e n d ();
brea k;
case 4 :
cdll_inser t_mid();
brea k;
case 5 :
cdll_delet e_b e g ();
brea k;
case 6 :
cdll_delet e_last();
brea k;
case 7 :
cdll_delet e_mi d();
brea k;
case 8 :
cdll_display_left_rig h t();
brea k;
case 9 :
107
cdll_display_rig h t_left();
brea k;
case 10:
exit(0);
}
getch();
}
}
top
400
d at a n e xt
40 X
400
30 400
300
20 300
200
st art
100 10 200
100
Fi g u r e 6 . 9 . 1 . L i n k e d s t a c k
re pr e s e nt at io n
stru ct stack
{
int data;
stru ct stack *next;
};
void push();
void pop();
void display();
typed ef struct stack node;
node *start = N U L L;
node *top = NULL;
108
scanf("%d", &tem p -> dat a);
tem p -> next = NULL;
retu r n tem p;
}
void pop()
{
node *temp;
if(top = = NULL)
{
printf("\n\n\t Stack unde rflow");
retu r n ;
}
tem p = start;
if( start -> next = = NULL)
{
printf("\n\n\t Popp e d elem e n t is %d ", top -> data);
star t = NULL;
free(top);
top = NULL;
}
else
{
while(te m p -> next != top)
{
tem p = temp -> next;
}
tem p -> next = NULL;
printf("\n\n\t Popp e d elem e n t is %d ", top -> data);
free(top);
top = temp;
}
}
void display()
{
node *temp;
if(top = = NULL)
{
printf("\n\n\t\t Stack is empty ");
}
else
{
tem p = start;
printf("\n\n\n\t\t Elem e n t s in the stack: \n");
109
printf("%5d ", tem p -> data);
while(te m p != top)
{
tem p = temp -> next;
printf("%5d ", tem p -> data);
}
}
}
char menu()
{
char ch;
clrscr();
printf("\n \tStack oper a tio n s using point e r s .. ");
printf("\n -----------**********-------------\n");
printf("\n 1. Push ");
printf("\n 2. Pop ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Ente r your choice: ");
ch = getch e();
retu r n ch;
}
void main()
{
char ch;
node *newnod e;
do
{
ch = men u();
switch(c h)
{
case '1' :
newno d e = getno d e();
push(n e w n o d e );
brea k;
case '2' :
pop();
brea k;
case '3' :
display();
brea k;
case '4':
retu r n ;
}
getch();
}while( ch != '4' );
}
110
fr o nt rear
100 400
Fi g u r e 6 . 1 0 . 1 . L i n k e d Q u e u e r e p r e s e n t a t i o n
stru ct que u e
{
int data;
stru ct que u e *next;
};
111
}
tem p = front;
front = front -> next;
printf("\n\n\t Delete d elem e n t from queu e is %d ", temp -> data);
free(t e m p );
}
void displayQ()
{
node *temp;
if(front = = NULL)
{
printf("\n\n\t\t Empty Queu e ");
}
else
{
tem p = front;
printf("\n\n\n\t\t Elem e n t s in the Queu e are: ");
while(te m p != NULL )
{
printf("%5d ", tem p -> data);
tem p = temp -> next;
}
}
}
char menu()
{
char ch;
clrscr();
printf("\n \t..Que u e oper a tio n s using point e r s .. ");
printf("\n\t -----------**********-------------\n");
printf("\n 1. Inser t ");
printf("\n 2. Delete ");
printf("\n 3. Display");
printf("\n 4. Quit ");
printf("\n Ente r your choice: ");
ch = getch e();
retu r n ch;
}
void main()
{
char ch;
do
{
ch = men u();
switch(c h)
{
case '1' :
insert Q();
brea k;
case '2' :
delet e Q();
brea k;
case '3' :
displayQ();
brea k;
case '4':
retu r n ;
}
getch();
} while(ch != '4');
}
112
113
Unit
4 Trees
Som e data orga niz a tio n s requir e cate g o rizin g data into grou p s /s u b-
group s . A data struc t u r e is said to be non linea r if its elem e n t s form a
hiera r c h ic al classification wher e, d ata items appe a r at various levels.
Trees and Graphs are widely used non-linear data structures. Tree and graph structures represents
hierarchial relationship between individual data elements. Graphs are nothing but trees with certain
restrictions removed.
7.1. TREES:
A tree t is a finite non-empty set of elements. One of these elements is called the root, and the
remaining elements (if any) are partitioned into trees, which are called the subtrees of t. A node
without a parent is called the root node (or root). Nodes with no children are called leaf nodes.
1
r1 r2 rn
. . . . .
2 3 4 5
T1 T2 Tn 6 7 8 9 10 11
. . . . .
F i g u r e 7 . 1 . 1 . R e c u r s iv e s t r u c t u r e o f t r e e a n d m - a r y t r e e
In the figure 7.1.1, r is a root node and T1, T2,..., Tn are trees with roots r1, r2,..., rn, respectively, then
we can construct a new tree whose root is r and T1, T2,..., Tn are the subtrees of the root. The nodes
r1, r2,..., rn are called the children of r.
In a tree data structure, there is no distinction between the various children of a node i.e., none is the
"first child" or "last child". A tree in which such distinctions are made is called an ordered tree, and
data structures built on them are called ordered tree data structures. Ordered trees are by far the
commonest form of tree data structure.
A special kind of tree called binary tree is easy to maintain in the computer.
A binary tree is a tree in which each node can have at most two children.
A binary tree is either empty or consists of a node called the root together with two binary trees
called the left subtree and the right subtree.
A tree with no nodes is called as a null tree. A binary tree is shown in figure 7. 2.
114
A
lef t c h ild B C ri g ht c h i l d
ri g ht s u bt r e e
l ef t s u bt r e e D E F G
H I
Fi g u r e 7 . 2 . 1 . Bi n a r y T r e e
Tree Terminology:
Leaf node:
A node with no children is called a leaf (or external node). A node which is not a leaf is called
an internal node.
Path
A sequence of nodes n1, n2, . . ., nk, such that ni is the parent of ni + 1 for i = 1, 2,. . ., k - 1. The
length of a path is 1 less than the number of nodes on the path. Thus there is a path of length
zero from a node to itself.
For the tree shown in figure 7.2.1, the path between A and I is A, B, D, I.
Siblings
For the tree shown in figure 7.2.1, F and G are the siblings of the parent node B and H and I
are the siblings of the parent node D.
Anc e s t o r and De s c e n d e n t
Subtree
Level
The level of the node refers to its distance from the root. The root of the tree has level O, and
the level of any other node in the tree is one more than the level of its parent. For example, in
the binary tree of Figure 7.2.1 node F is at level 2 and node H is at level 3.
Height
The maximum level in a tree determines its height. The height of a node in a tree is the length
of a longest path from the node to a leaf. The term depth is also used to denote height of the
tree. The height of the tree of Figure 7.2.1 is 3.
The nodes of a binary tree can be numbered in a natural way, level by level, left to right. The
nodes of an complete binary tree can be numbered so that the root is assigned the number 1,
115
a left child is assigned twice the number assigned its parent, and a right child is assigned one
more than twice the number assigned its parent. For example, see Figure 7.2.2.
Level 0
1
Level 1
2 3
Level 2
4 5 6 7
Level 3
8 9
3. Since a binary tree can contain at most one node at level 0 (the root), it can contain at most 2 l
node at level l.
If every non-leaf node in a binary tree has nonempty left and right subtrees, the tree is termed
a strictly binary tree. Thus the tree of figure 7.2.3(a) is strictly binary. A strictly binary tree with
n leaves always contains 2n - 1 nodes.
A full binary tree of height h has all its leaves at level h. Alternatively; All non leaf nodes of a full
binary tree have two children, and the leaf nodes have no children.
A full binary tree with height h has 2h + 1 - 1 nodes. A full binary tree of height h is a strictly
binary tree all of whose leaves are at level h. Figure 7.2.3(d) illustrates the full binary tree
containing 15 nodes and of height 3.
116
1
1 S t r ic t B i n a r y T r e e
( a)
2 3
2 3
6 7 4 5 6 7
12 13 8 9 S t r ic t ly C o m p l e t e ( b)
b in ary t r e e
1
1
2 3
2 3
4 5 6 7
4 5 6 7
8 9 10 11 12 13 14 15
8 9 10
Co m p l e t e b i n ary t r e e (c ) Fu l l b i n a r y t r e e ( d)
Fi g u r e 7 . 2 . 3 . E x a m p l e s o f b i n a r y t r e e s
A binary tree with n nodes is said to be complete if it contains all the first n nodes of the
above numbering scheme. Figure 7.2.4 shows examples of complete and incomplete binary
trees.
A compl et e bina ry tre e of heigh t h looks like a full bina ry tree down
to level h- 1, and the level h is filled from left to right.
A complete binary tree with n leaves that is not strictly binary has 2n nodes. For example, the
tree of Figure 7.2.3(c) is a complete binary tree having 5 leaves and 10 nodes.
1 1 1
2 3 2 3 2
4 5 6 4 5 7 4
Co m p l e t e Bi n a ry T r e e No t Co m p l e t e a n d No t Co m p l e t e a n d
b u t n o t st r ic t n o t s t r ic t n o t s t r ic t
( a) ( b) (c )
Fi g u r e 7 . 2 . 4 . E x a m p l e s o f c o m p l e t e a n d i n c o m p l e t e b i n a r y t r e e s
A binary search tree is a binary tree. It may be empty. If it is not empty then it satisfies the following
properties:
1. Every element has a key and no two elements have the same key.
2. The keys in the left subtree are smaller than the key in the root.
3. The keys in the right subtree are larger than the key in the root.
117
4. The left and right subtrees are also binary search trees.
Figure 7.2.5(a) is a binary search tree, whereas figure 7.2.5(b) is not a binary search tree.
16 16
12 20 12 20
11 14 19 11 14 19
7
13 13 17
Fi g u r e 7 . 2 . 5 . Ex a m p l e s o f b i n a r y s e a r c h trees
Array-based Implementation:
Binary trees can also be stored in arrays, and if the tree is a complete binary tree, this method wastes
no space. In this compact arrangement, if a node has an index i, its children are found at indices 2i+1
and 2i+2, while its parent (if any) is found at index floor((i-1)/2) (assuming the root of the tree stored in
the array at an index zero).
This method benefits from more compact storage and better locality of reference, particularly during a
preorder traversal. However, it requires contiguous memory, expensive to grow and wastes space
proportional to 2h - n for a tree of height h with n nodes.
0 1 2 3 4 5 6
Array representation is good for complete binary tree, but it is wasteful for many other binary trees.
The representation suffers from insertion and deletion of node from the middle of the tree, as it
requires the moment of potentially many nodes to reflect the change in level number of this node. To
overcome this difficulty we represent the binary tree in linked representation.
In linked repr e s e n t a t i o n eac h node in a bina ry has thre e fields, the left
child field denot e d as LeftChild , dat a field denot e d as data and the right
child field denot e d as RightC hild . If any sub- tree is empty then the
corr e s p o n d i n g point e r’s LeftChild and RightC hild will stor e a NULL
value. If the tre e itself is empty the root point e r will store a NULL value.
118
Inse r tio n and deletion involve no dat a move m e n t and no
move m e n t of node s excep t the rear r a n g e m e n t of point e r s .
Memo ry spac e s are wast e d for storing NULL point e r s for the
node s, which have no subt r e e s .
st r u ct b i n a r y t r e e node:
{
st r u ct b i n a r y t r e e * L e f t C h i ld ;
int d at a; Lef t Ch i l d d at a Ri g h t C h i l d
st r u ct b i n a r y t r e e * Ri g h t C h i l d ;
};
Em pty Tr e e :
t y p e d e f st r u ct b i n a r y t r e e n o d e ; r o ot
NULL
n o d e * r o o t = N U L L;
Fi g u r e 7 . 2 . 6 . S t r u c t u r e d e f i n it i o n , n o d e r e p r e s e n t a t i o n a n d e m p t y t r e e
A
ro ot
B C
A
D E F G
H I B C
D X E X X F X X G X
X H X X I X
Fi g u r e 7 . 2 . 7 . L i n k e d r e p r e s e n t a t i o n f o r t h e b i n a r y t r e e
Sear c h mea n s finding a path or trave r s al betw e e n a star t node and one
of a set of goal nodes . Sea rc h involves visiting node s in a gra p h in a
syste m a t i c man n e r , and may or may not res ult into a visit to all node s.
119
When the sear c h nece s s a rily involved the exa min a tio n of every vert ex in
the tree, it is called the trave r s a l.
Ther e are four comm o n ways to trave r s e a bina ry tre e:
1. Preo r d e r
2. Inord e r
3. Postor d e r
4. Level orde r
Inor d e r Traver s a l:
In the case of inorder traversal, the root of each subtree is visited after its left subtree has been
traversed but before the traversal of its right subtree begins. The steps for traversing a binary tree in
inorder traversal are:
Pre or d e r Traver s a l:
In a preorder traversal, each root node is visited before its left and right subtrees are traversed.
Preorder search is also called backtracking. The steps for traversing a binary tree in preorder
traversal are:
120
print root -> data;
preo r d e r (root -> lchild);
preo r d e r (root -> rchild);
}
}
Pos t o r d e r Traver s a l:
In a postor d e r trave r s al, each root is visited after its left and right
subt r e e s have bee n trave r s e d . The steps for trave r si n g a bina ry tre e in
posto r d e r trave r s a l are:
In a level order traversal elements are visited by level from top to bottom. Within levels, elements are
visited from left to right. The level order traversal requires a queue data structure. So, it is not possible
to develop a recursive procedure to traverse the binary tree in level order. This is nothing but a
breadth first search technique.
void levelor d e r ()
{
int j;
for(j = 0; j < ctr; j+ + )
{
if(tre e[j] != NULL)
print tree[j] -> data;
}
}
121
Exa m p l e 1:
Traverse the following binary tree in pre, post, inorder and level order.
A Pr eo r d e r t r a v e r s a l y i e l ds:
A , B , D , C , E, G , F, H , I
B C
Po st o r d e r t r a v e r s a l y i e l ds:
D , B , G , E, H , I , F, C , A
D E F
I n o r d e r t r a v e r s a l y i e l ds:
G H I D , B , A , E, G , C , H , F, I
Le v e l o r d e r t r a v e r s a l y i e l ds:
A , B , C , D , E, F, G , H , I
Bi n a r y T r e e Pr e , Po st , I n o r d e r a n d l e v e l o r d e r T r a v e r s i n g
Exa m p l e 2:
Traverse the following binary tree in pre, post, inorder and level order.
Pr e o r d e r t r a v e r s a l y i e l d s :
P
P, F , B , H , G , S , R, Y, T , W , Z
F S
Po st o r d e r t r a v e r s a l y i e l d s:
B H R Y
B , G , H , F , R, W , T , Z , Y, S , P
I n o r d e r t r a v e rs a l y ie lds:
G T Z B , F , G , H , P, R, S , T , W , Y, Z
W L e v e l o r d e r t r a v e r s a l y i e l d s:
P, F , S , B , H , R, Y, G , T , Z , W
Bi n a r y T r e e Pr e , Po s t , I n o r d e r a n d l e v e l o r d e r T r a v e r s i n g
Exa m p l e 3:
Traverse the following binary tree in pre, post, inorder and level order.
Pr e o r d e r t r a v e r s a l y i e l d s:
2
2, 7 , 2 , 6 , 5 , 11 , 5 , 9 , 4
7 5
Po st o r d e r t r a v a r s a l y i e l d s:
2, 5 , 11 , 6 , 7 , 4 , 9 , 5 , 2
2 6 9
I n o r d e r t r a v a r s a l y i e l d s:
5 11 4 2, 7 , 5 , 6 , 11 , 2 , 5 , 4 , 9
L e v e l o r d e r t r a v e r s a l y i e l d s:
2, 7 , 5 , 2 , 6 , 9 , 5 , 11 , 4
Bi n a ry T r e e Pr e , P o s t , I n o r d e r a n d l e v e l o r d e r T r a v e r s i n g
Exa m p l e 4:
Traverse the following binary tree in pre, post, inorder and level order.
122
Pr e o r d e r t r a v e r s a l y i e l d s:
A A, B, D , G , K, H , L, M , C , E
B C
Po st o r d e r t r a v a r s a l y i e l d s:
K , G , L , M , H , D , B , E, C , A
D E
I n o r d e r t r a v a r s a l y i e l d s:
G H K , G , D , L , H , M , B , A , E, C
K L M L e v e l o r d e r t r a v e r s a l y i e l d s:
A , B , C , D , E, G , H , K , L , M
Bi n a ry T r e e Pr e , P o s t , I n o r d e r a n d l e v e l o r d e r T r a v e r s i n g
It can be noted that, for the purpo s e mentio n e d , two trave r s a l are
ess e n ti al out of which one should be inord e r trave r s a l and anot h e r
preo r d e r or posto r d e r ; alter n a t iv ely, given preo r d e r and posto r d e r
trave r s a l s, binary tree canno t be obtain e d uniqu ely.
Exa m p l e 1:
Preorder: A B D G C E H I F
Inorder: D G B A H E I C F
Solution:
123
A
D G B H E I C F
From the inord e r sequ e n c e D G B, we can find that D and G are to the
left of B.
B H E I C F
D G
From the inord e r sequ e n c e D G, we can find that ther e is no left node to
D and G is at the right of D.
The Binary tree upto this point looks like:
A
B H E I C F
From the preorder sequence C E H I F, the root of the left sub tree is: C
124
A
B C
D H E I F
125
A
B C
D E F
G H I
Example 2:
Inorder: n1 n2 n3 n4 n5 n6 n7 n8 n9
Postorder: n1 n3 n5 n4 n2 n8 n7 n9 n6
Solution:
n6
n1 n2 n3 n4 n5 n7 n8 n9
137
n6
n2 n7 n8 n9
n1 n3 n4 n5
To find the root, left and right sub tree s for n3 n4 n5:
From the postorder sequence n3 n5 n4, the root of the tree is: n4
n2 n7 n8 n9
n1 n4
n3 n5
To find the root, left and right sub tree s for n7 n8 and n9:
From the postorder sequence n8 n7 n9, the root of the left sub tree is: n9
n2 n9
n1 n4 n7 n8
n3 n5
To find the root, left and right sub tree s for n7 and n8:
From the postorder sequence n8 n7, the root of the tree is: n7
138
The Binary tree upto this point looks like:
n6
n2 n9
n1 n4 n7
n3 n5 n8
struct tree
{
stru ct tree* lchild;
char data[1 0];
stru ct tree* rchild;
};
139
{
tree[ i * 2 + 1 ] = getno d e();
tree[i]- >lchild = tree[i * 2 + 1];
j--;
}
if( j > 0 ) /* right child */
{
tree[i * 2 + 2] = getno d e ();
j--;
tree[i]- > rc hild = tree[i * 2 + 2];
}
i+ + ;
} while( j > 0);
}
140
retu r n 0;
}
if(root- >lchild = = NULL && root- > rc hild = = NULL)
retu r n 0;
else
retu r n (1 + max(heig h t( r oo t- >lchild), height(r oo t- > rc hild)));
}
void main()
{
int i;
creat e_fbin a ry t r e e ();
printf("\n Inord e r Trave r s al: ");
inord e r( t r e e [ 0]);
printf("\n Preo r d e r Traver s al: ");
preo r d e r ( t r e e [ 0]);
printf("\n Postor d e r Trave r s al: ");
postor d e r ( t r e e [ 0]);
printf("\n Level Order Traversal: ");
levelor d e r ();
printf("\n Leaf Node s: ");
print_leaf(t r e e [ 0]);
printf("\n Heigh t of Tree: %d ", heigh t(t r e e [ 0]));
}
stru ct tree
{
stru ct tree* lchild;
char data[1 0];
stru ct tree* rchild;
};
141
if( root != NULL )
{
printf("\n Node %s has Left SubTr e e(Y/N)",root- > d a t a );
fflush(st din);
scanf("%c",&op tion);
if( option = = 'Y' || option = = 'y')
{
root- >lchild = getno d e();
creat e_bin a r y t r e e ( r o o t- >lchild);
}
else
{
root- >lchild = NULL;
creat e_bin a r y t r e e ( r o o t- >lchild);
}
142
inord e r( r o o t- > rc hild);
}
}
int menu()
{
int ch;
143
clrscr();
printf("\n 1. Crea t e Binary Tree ");
printf("\n 2. Inord e r Traver s al ");
printf("\n 3. Preor d e r Trave r s al ");
printf("\n 4. Postor d e r Traver s al ");
printf("\n 5. Level Order Trave r s al");
printf("\n 6. Leaf Node ");
printf("\n 7. Print Height of Tree ");
printf("\n 8. Print Binary Tree ");
printf("\n 9. Delete a node ");
printf("\n 10. Quit ");
printf("\n Ente r Your choice: ");
scanf("%d", &ch);
retu r n ch;
}
void main()
{
int i,ch;
node *root = NULL;
do
{
ch = men u();
switch( ch)
{
case 1 :
if( root = = NULL )
{
root = getno d e();
creat e_bin a r y t r e e ( r o o t);
}
else
{
printf("\n Tree is alre a dy Creat e d ..");
}
brea k;
case 2 :
printf("\n Inord e r Trave r s al: ");
inord e r( r o o t);
brea k;
case 3 :
printf("\n Preo r d e r Traver s al: ");
preo r d e r ( r o o t);
brea k;
case 4 :
printf("\n Postor d e r Trave r s al: ");
postor d e r ( r o o t);
brea k;
case 5:
printf("\n Level Orde r Traver s al ..");
make_Qu e u e ( r o o t, 0);
level_ord e r(Q, no d e_c t r);
brea k;
case 6 :
printf("\n Leaf Node s: ");
print_leaf(root);
brea k;
case 7 :
printf("\n Heigh t of Tree: %d ", heigh t(r oo t));
brea k;
case 8 :
printf("\n Print Tree \n");
print_tr e e( r oo t, 0);
brea k;
case 9 :
delet e_no d e ( r oo t, 0);
brea k;
case 10 :
exit(0);
144
}
getch();
}while(1);
}
We can also trave r s e a bina ry tre e non recu r s ively using stack data
stru c t u r e for inord e r, preor d e r and postor d e r .
Inor d e r Traver s a l:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex, pushing each vertex onto the stack and
stop when there is no left son of vertex.
2. Pop and proce s s the nodes on stack if zero is popp e d then exit. If a
vert ex with right son exists, then set right son of vert ex as curr e n t
vert ex and ret u r n to step one.
Algori t h m inord e r ()
{
stack[1] = 0
vert ex = root
top: while(ve r t e x ≠ 0)
{
pus h the vertex into the stack
vert ex = leftson(ve r t e x)
}
while(ver t e x ≠ 0)
{
print the vertex node
if(rights o n(ve r t e x) ≠ 0)
{
vert ex = right s o n(v e r t e x)
goto top
}
pop the elem e n t from the stack and mad e it as vert ex
}
}
Preorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
145
1. Proceed down the left most path by pushing the right son of vertex onto stack, if any and
process each vertex. The traversing ends after a vertex with no left child exists.
2. Pop the vertex from stack, if vertex ≠0 then return to step one otherwise exit.
Algori t h m preo r d e r ( )
{
stack[1] = 0
vert ex = root.
while(ver t e x ≠ 0)
{
print vertex node
if(rights o n(ve r t e x) ≠ 0)
pus h the right son of vertex into the stack.
if(leftso n(ve r t e x) ≠ 0)
vert ex = leftson(ve r t e x)
else
pop the elem e n t from the stack and mad e it as vert ex
}
}
Postorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex. At each vertex of path push vertex on to
stack and if vertex has a right son push –(right son of vertex) onto stack.
2. Pop and process the positive nodes (left nodes). If zero is popped then exit. If a negative
node is popped, then ignore the sign and return to step one.
Algori t h m posto r d e r ( )
{
stack[1] = 0
vert ex = root
top: while(ve r t e x ≠ 0)
{
pus h vertex onto stack
if(rights o n(ve r t e x) ≠ 0)
pus h – (vert ex) onto stack
vert ex = leftson(ve r t e x)
}
pop from stack and make it as vertex
while(ver t e x > 0)
{
146
print the vertex node
pop from stack and make it as vertex
}
if(vert ex < 0)
{
vert ex = - (vert ex)
goto top
}
}
Example 1:
Traverse the following binary tree in pre, post and inorder using non-recursive
traversing algorithm.
A
Pr e o r d e r t r a v e r s a l y i e l d s:
B C A, B, D , G , K, H , L, M , C , E
D E Po st o r d e r t r a v a r s a l y i e l d s:
K , G , L , M , H , D , B , E, C , A
G H
I n o r d e r t r a v a r s a l y i e l d s:
K , G , D , L , H , M , B , A , E, C
K L M
Bi n a ry T r e e Pr e , P o s t a n d I n o r d e r T r a v e r s i n g
Inorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex, pushing each vertex onto the stack and
stop when there is no left son of vertex.
2. Pop and process the nodes on stack if zero is popped then exit. If a vertex with right son
exists, then set right son of vertex as current vertex and return to step one.
Current
Stack Processed nodes Remarks
vertex
A 0 PUSH 0
0ABDGK PUSH the left most path of A
K 0ABDG K POP K
G 0ABD KG POP G since K has no right son
D 0AB KGD POP D since G has no right son
H 0AB KGD Make the right son of D as vertex
H 0ABHL KGD PUSH the leftmost path of H
L 0ABH KGDL POP L
H 0AB KGDLH POP H since L has no right son
M 0AB KGDLH Make the right son of H as vertex
0ABM KGDLH PUSH the left most path of M
147
M 0AB KGDLHM POP M
B 0A KGDLHMB POP B since M has no right son
A 0 KGDLHMBA Make the right son of A as vertex
C 0CE KGDLHMBA PUSH the left most path of C
E 0C KGDLHMBAE POP E
C 0 KGDLHMBAEC Stop since stack is empty
Postorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex. At each vertex of path push vertex on to
stack and if vertex has a right son push –(right son of vertex) onto stack.
2. Pop and process the positive nodes (left nodes). If zero is popped then exit. If a negative
node is popped, then ignore the sign and return to step one.
Current
Stack Processed nodes Remarks
vertex
A 0 PUSH 0
PUSH the left most path of A with a
0 A –C B D –H G K
-ve for right sons
0 A –C B D –H KG POP all +ve nodes K and G
H 0 A –C B D KG Pop H
PUSH the left most path of H with a
0 A –C B D H –M L KG
-ve for right sons
0 A –C B D H –M KGL POP all +ve nodes L
M 0 A –C B D H KGL Pop M
PUSH the left most path of M with a
0 A –C B D H M KGL
-ve for right sons
0 A –C KGLMHDB POP all +ve nodes M, H, D and B
C 0A KGLMHDB Pop C
PUSH the left most path of C with a
0ACE KGLMHDB
-ve for right sons
0 KGLMHDBECA POP all +ve nodes E, C and A
0 Stop since stack is empty
Preorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path by pushing the right son of vertex onto stack, if any and
process each vertex. The traversing ends after a vertex with no left child exists.
2. Pop the vertex from stack, if vertex ≠0 then return to step one otherwise exit.
Current
Stack Processed nodes Remarks
vertex
A 0 PUSH 0
PUSH the right son of each vertex onto stack
0CH ABDGK
and process each vertex in the left most path
148
H 0C ABDGK POP H
PUSH the right son of each vertex onto stack
0CM ABDGKHL
and process each vertex in the left most path
M 0C ABDGKHL POP M
PUSH the right son of each vertex onto stack
0C ABDGKHLM and process each vertex in the left most path;
M has no left path
C 0 ABDGKHLM Pop C
PUSH the right son of each vertex onto stack
0 ABDGKHLMCE and process each vertex in the left most path;
C has no right son on the left most path
0 ABDGKHLMCE Stop since stack is empty
Example 2:
Traverse the following binary tree in pre, post and inorder using non-recursive
traversing algorithm.
2 Pr e o r d e r t r a v e r s a l y i e l d s:
2, 7 , 2 , 6 , 5 , 11 , 5 , 9 , 4
7 5
Po st o r d e r t r a v a r s a l y i e l d s:
2 6 9 2, 5 , 11 , 6 , 7 , 4 , 9 , 5 , 2
5 11 4 I n o r d e r t r a v a r s a l y i e l d s:
2, 7 , 5 , 6 , 11 , 2 , 5 , 4 , 9
Bi n a ry T r e e Pr e , P o s t a n d I n o r d e r T r a v e r s i n g
Inorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex, pushing each vertex onto the stack and
stop when there is no left son of vertex.
2. Pop and process the nodes on stack if zero is popped then exit. If a vertex with right son
exists, then set right son of vertex as current vertex and return to step one.
Current
Stack Processed nodes Remarks
vertex
2 0
0272
2 027 2
7 02 27
6 0265 27
5 026 275
11 02 2 7 5 6 11
149
5 05 2 7 5 6 11 2
9 094 2 7 5 6 11 2 5
4 09 2 7 5 6 11 2 5 4
0 2 7 5 6 11 2 5 4 9 Stop since stack is empty
Postorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path rooted at vertex. At each vertex of path push vertex on to
stack and if vertex has a right son push –(right son of vertex) onto stack.
2. Pop and process the positive nodes (left nodes). If zero is popped then exit. If a negative
node is popped, then ignore the sign and return to step one.
Current
Stack Processed nodes Remarks
vertex
2 0
0 2 –5 7 –6 2
2 0 2 –5 7 –6 2
6 0 2 –5 7 2
0 2 –5 7 6 –11 5 2
5 0 2 –5 7 6 –11 25
11 0 2 –5 7 6 11 25
0 2 –5 2 5 11 6 7
5 0 2 5 –9 2 5 11 6 7
9 02594 2 5 11 6 7
0 2 5 11 6 7 4 9 5 2 Stop since stack is empty
Preorder Traversal:
Initially push zero onto stack and then set root as vertex. Then repeat the following steps until the
stack is empty:
1. Proceed down the left most path by pushing the right son of vertex onto stack, if any and
process each vertex. The traversing ends after a vertex with no left child exists.
2. Pop the vertex from stack, if vertex ≠0 then return to step one otherwise exit.
Current
Stack Processed nodes Remarks
vertex
2 0
056 272
6 0 5 11 27265
11 05 27265
05 2 7 2 6 5 11
5 09 2 7 2 6 5 11
9 0 2 7 2 6 5 11 5
0 2 7 2 6 5 11 5 9 4 Stop since stack is empty
150
7.4. Expression Trees:
Expression tree is a binary tree, because all of the operations are binary. It is also possible for a node
to have only one child, as is the case with the unary minus operator. The leaves of an expression tree
are operands, such as constants or variable names, and the other (non leaf) nodes contain operators.
Inorder Traversal
Preorder Traversal
Postorder Traversal
Figure 7.4.1 shows some more expression trees that represent arithmetic expressions given in infix
form.
+ +
+ / + d
a b c d + c
( a) ( a + b) + ( c / d) ( b) ( ( a + b) + c ) + d
a b
+ *
- + + *
a x y b c a
(c ) ( (- a) + ( x + y ) ) / ( ( + b ) * ( c * a) )
Fi g u r e 7 . 4 . 1 Ex p r e s s i o n T r e e s
An expression tree can be generated for the infix and postfix expressions.
2. If the symbol is an operand, we create a one-node tree and push a pointer to it onto a
stack.
3. If the symbol is an operator, we pop pointers to two trees T1 and T2 from the stack (T1 is
popped first) and form a new tree whose root is the operator and whose left and right
children point to T2 and T1 respectively. A pointer to this new tree is then pushed onto
the stack.
Example 1:
The first two symbols are operands, so we create one-node trees and push pointers to them onto a
stack.
151
a b
Next, a ‘+’ is read, so two pointers to trees are popped, a new tree is formed, and a pointer to it is
pushed onto the stack.
a b
Next, c, d, and e are read, and for each one–node tree is created and a pointer to the corresponding
tree is pushed onto the stack.
a b c d e
+
+ c +
a bb d e
Continuing, a ‘*’ is read, so we pop two tree pointers and form a new tree with a ‘*’ as root.
+
+ *
a b c +
d ee
Finally, the last symbol is read, two trees are merged, and a pointer to the final tree is left on the
stack.
152
+
*
+ *
a b c +
d e
e
Example 2:
(A + B * C) – ((D * E + F) / G)
Solution:
The first three symbols are operands, so we create one-node trees and pointers to three nodes
pushed onto the stack.
A B C
Next, a ‘*’ is read, so two pointers to trees are popped, a new tree is formed, and a pointer to it is
pushed onto the stack.
A *
B C
Next, a ‘+’ is read, so two pointers to trees are popped, a new tree is formed, and a pointer to it is
pushed onto the stack.
153
+
A
*
B C
Next, D and E are read, and for each one–node tree is created and a pointer to the corresponding
tree is pushed onto the stack.
+ D E
A
*
B C
Continuing, a ‘*’ is read, so we pop two tree pointers and form a new tree with a ‘*’ as root.
+ *
A * D E
B C
Proceeding similar to the previous steps, finally, when the last symbol is read, the expression tree is
as follows:
154
+
-
+ /
A * + G
B C * F
D E
UNIT- 5 GRAPHS
Graph G is a pair (V, E), where V is a finite set of vertices and E is a finite set of edges. We will often
denote n = |V|, e = |E|.
A gra p h is gen e r a lly displaye d as figur e 7.5.1, in which the vertice s are
repr e s e n t e d by circles and the edge s by lines.
An edge with an orient a tio n (i.e., arrow hea d) is a direc t e d edge, while
an edg e with no orien t a ti o n is our undire c t e d edg e.
155
A direc t e d gra p h G is said to be conne c t e d , or stron gly conn e c t e d , if for
each pair u, v for node s in G ther e is a path from u to v and the r e is a
pat h from v to u. On the othe r hand, G is said to be unilat e r ally
conn e c t e d if for any pair u, v of node s in G ther e is a path from u to v or
a path from v to u. For exam pl e, the digra p h show n in figur e 7.5.1 (e) is
stron gly conn e c t e d .
B D v1
A B
E
A C E G v4 v2
C D
( a) ( b) v3 (c )
F
v1 v1 v1 v1
v2 v3
v4 v2 v4 v2 v4 v2
( d) ( e) (f) ( g)
v3 v3 v3 v4 v5 v6 v7
Fi g u r e 7 . 5 . 1 V a r i o u s Gr a p h s
We can assign weight function to the edges: w G (e) is a weight of edge e E. The graph which has
such function assigned is called weighted graph.
The number of incoming edges to a vertex v is called in–degree of the vertex (denote indeg(v)). The
number of outgoing edges from a vertex is called out-degree (denote outdeg(v)). For example, let us
consider the digraph shown in figure 7.5.1(f),
indegree(v1) = 2 outdegree(v1) = 1
indegree(v2) = 2 outdegree(v2) = 0
A path is a sequence of vertices (v 1, v2, . . . . . . , vk), where for all i, (vi, vi+1) E. A path is simple if all
vertices in the path are distinct. If there a path containing one or more edges which starts from a
vertex Vi and terminates into the same vertex then the path is known as a cycle. For example, there is
a cycle in figure 7.5.1 (a), figure 7.5.1 (c) and figure 7.5.1 (d).
If a graph (digraph) does not have any cycle then it is called acyclic graph. For example, the graphs
of figure 7.5.1 (f) and figure 7.5.1 (g) are acyclic graphs.
A Forest is a set of disjoint trees. If we remove the root node of a given tree then it becomes forest.
The following figure shows a forest F that consists of three trees T1, T2 and T3.
156
A P X
B D Y
Q R
Z
T1 C E F T2 T3
A F or e s t F
A graph that has either self loop or parallel edges or both is called multi-graph.
Tree is a connected acyclic graph (there aren’t any sequences of edges that go around in a loop). A
spanning tree of a graph G = (V, E) is a tree that contains all vertices of V and is a subgraph of G. A
single graph can have multiple spanning trees.
Representation of Graphs:
Adjacency matrix.
Adjacency List.
Incidence matrix.
Adjacency matrix:
In this representation, the adjacency matrix of a graph G is a two dimensional n x n matrix, say A =
(ai,j), where
1 1 2 3 4 5
1 0 1 1 0 1
2 3
G1 : 2 0 0 1 1 1
3 0 0 0 1 0
( a) 4 5 (b) 4 0 0 0 0 0
5 0 0 1 1 0
Fi g u r e 7 . 5 . 2 . A g r a p h a n d it s A d j a c e n c y m a t r i x
Figure 7.5.2(b) shows the adjacency matrix representation of the graph G1 shown in figure 7.5.2(a).
The adjacency matrix is also useful to store multigraph as well as weighted graph. In case of
157
multigraph representation, instead of entry 0 or 1, the entry will be between number of edges between
two vertices.
In case of weighted graph, the entries are weights of the edges between the vertices. The adjacency
matrix for a weighted graph is called as cost adjacency matrix. Figure 7.5.3(b) shows the cost
adjacency matrix representation of the graph G2 shown in figure 7.5.3(a).
G2:
B
4
D A B C D E F G
3 1 4 A 0 3 6
2 2
4 1
B 3 0 2 4
A C E G
6 C 6 2 0 1 4 2
2
2
1 D 4 1 0 2 4
( a) (b)
F E 4 2 0 2 1
F 2 2 0 1
a n d it s
Fi g u r e 7 . 5 . 3 W e i g h t e d g r a p h
G C o s t a d j 4
ac e nc y
1 1
ma t rix
0
Adjac e n c y List :
1 2 3
1 1 1 1 2 3
1 1
2 3
2 0 0 1
3 0 1 0 3 2
( a) A d j ac e nc y Mat r ix ( b) A d j ac e nc y Li st
Fi g u r e 7 . 5 . 4 A d j a c e n c y m a t r i x a n d a d j a c e n c y l i s t
Incidence Matrix:
In this representation, if G is a graph with n vertices, e edges and no self loops, then incidence matrix
A is defined as an n by e matrix, say A = (ai,j), where
Here, n rows correspond to n vertices and e columns correspond to e edges. Such a matrix is called
as vertex-edge incidence matrix or simply incidence matrix.
158
B
c
D
a b c d e f g h i j k l
a d f A 1 0 0 0 0 0 1 0 0 0 0 0
b e
B 1 1 1 0 0 0 0 0 0 0 0 0
h i
A C E G C 0 1 0 1 0 0 1 1 0 0 1 0
g
k
j
l
D 0 0 1 1 1 1 0 0 0 0 0 0
( a)
F ( b)
E 0 0 0 0 1 0 0 1 1 1 0 0
F 0 0 0 0 0 0 0 0 0 1 1 1
G 0 0 0 0 0 1 0 0 1 0 0 1
Fi g u r e 7 . 5 . 4 Gr a p h a n d it s i n c i d e n c e m a t r i x
Figure 7.5.4(b) shows the incidence matrix representation of the graph G1 shown in figure 7.5.4(a).
A spanning tree for a connected graph is a tree whose vertex set is the same as the vertex set of the
given graph, and whose edge set is a subset of the edge set of the given graph. i.e., any connected
graph will have a spanning tree.
Weight of a spanning tree w(T) is the sum of weights of all edges in T. Minimum spanning tree (MST)
is a spanning tree with the smallest possible weight.
Example:
G:
A g r a p h G:
T h r e e ( o f m a n y p o s s i b l e ) s p a n n i n g t r e e s f r o m g r a p h G:
2 2
4
G: 3 5 3
6
1 1
A w e i g h t e d g r a p h G: T h e m i n i m a l s p a n n i n g t r e e f r o m w e i g h t e d g r a p h G:
One practical application of a MST would be in the design of a network. For instance, a
group of individuals, who are separated by varying distances, wish to be connected
together in a telephone network. Although MST cannot do anything about the distance
from one connection to another, it can be used to determine the least cost paths with no
cycles in this network, thereby connecting everyone at a minimum cost.
Another useful application of MST would be finding airline routes. The vertices of the
graph would represent cities, and the edges would represent routes between the cities.
MST can be applied to optimize airline routes by finding the least costly paths with no
cycles.
Minimum spanning tree, can be constructed using any of the following two algorithms:
159
1. Kruskal’s algorithm and
2. Prim algorithm.
Both algorithms differ in their methodology, but both eventually end up with the MST. Kruskal's
algorithm uses edges, and Prim’s algorithm uses vertex connections in determining the MST.
This is a greedy algorithm. A greedy algorithm chooses some local optimum (i.e. picking an edge with
the least weight in a MST).
Kruskal's algorithm works as follows: Take a graph with 'n' vertices, keep on adding the shortest
(least cost) edge, while avoiding the creation of cycles, until (n - 1) edges have been added.
Sometimes two or more edges may have the same cost.
The order in which the edges are chosen, in this case, does not matter. Different MST’s may result,
but they will all have the same total cost, which will always be the minimum cost.
Exa m p l e 1:
Const r u c t the minim al span ni n g tree for the grap h show n below:
10 50
1 2
45 40 3
30 35
4 25 5
55
20 15
6
Cost 10 15 20 25 30 35 40 45 50 55
Edge (1, 2) (3, 6) (4, 6) (2, 6) (1, 4) (3, 5) (2, 5) (1, 5) (2, 3) (5, 6)
160
Edg e Cost Sta g e s in Krus k a l’ s alg o ri t h m Re m a r k s
4
5
6
4
5
6
4
5
6
Exa m p l e 2:
Const r u c t the minim al span ni n g tree for the grap h show n below:
1 28
10
2
14
6 16
7
24 3
25
5 18
12
22 4
Sol u t i o n :
161
Arrang e all the edge s in the increasi n g order of their costs:
Cost 10 12 14 16 18 22 24 25 28
Edge (1, 6) (3, 4) (2, 7) (2, 3) (4, 7) (4, 5) (5, 7) (5, 6) (1, 2)
5
4
6
3
7
5
4
6
3
7
5
4
6
3
7
5
4
6
3
7
5
4
162
(5, 6) 25 1 Finally, the edge between vertices 5 and 6 is
2 considered and included in the tree built. This
completes the tree.
6
3
7 The cost of the minimal span ni n g tree is
99 .
5
4
Wars h all’s algorit h m requir e s to know which edge s exist and which do
not. It does n’t nee d to know the lengt h s of the edge s in the given
direc t e d gra p h. This inform a tio n is conveni e n tly displaye d by adjac e n cy
mat rix for the grap h, in which a ‘1’ indicat e s the existe n c e of an edge
and ‘0’ indicat e s non- existe n c e .
A l l P a ir s Re c h a b i l it y
A d j ac e nc y Mat r ix W a r s h a l l’ s A l g o r it h m
Mat r ix
It begins with the adjac e n cy matrix for the given gra p h, which is called
A0 , and then upd a t e s the mat rix ‘n’ times, prod u ci n g mat ric e s called A 1 ,
A2 , . . . . . , An and then stops.
In wars h all’s algorit h m the mat rix Ai mer ely contai n s inform a ti o n about
the existe n c e of i – path s. A 1 entry in the mat rix A i will corr e s p o n d to the
existe n c e of an i – path s and O entry will corr e s p o n d to non- existe n c e .
Thus when the algorit h m stops, the final mat rix, the mat rix A n , cont ai n s
the desire d conn e c tivity inform a ti o n.
The upd a t e rule for comp u ti n g Ai from Ai-1 in wars h a ll’s algorit h m is:
Ai [x, y] = Ai-1 [x, y] ۷ (A i-1 [x, i] ٨ Ai-1 [i, y]) ---- (1)
Exa m p l e 1:
Use wars h all’s algorit h m to calcula t e the reac h a b ility matrix for the
gra p h:
163
4
1 4
5 6
7 11
1
2 3
7
1 0 1 1 0
2 0 0 1 1
A0 0
3 0 0 0
4 1 1 1 0
The first step is to comp u t e ‘A 1 ’ mat rix. To do so we will use the upd a ti n g
rule – (1).
1 0 1 1 0
2 0 0 1 1
A1 0
3 0 0 0
4 1 1 1 0
164
A2 [3, 3] = A1 [3, 3] ۷ (A 1 [3, 2] ٨ A1 [2, 3]) = 0 ۷ (0 ٨ 1) = 0
A2 [3, 4] = A1 [3, 4] ۷ (A 1 [3, 2] ٨ A1 [2, 4]) = 0 ۷ (0 ٨ 1) = 0
A2 [4, 4] = A1 [4, 4] ۷ (A 1 [4, 2] ٨ A1 [2, 4]) = 0 ۷ (1 ٨ 1) = 1
1 0 1 1 1
2 0 0 1 1
A2 0
3 0 0 0
4 1 1 1 1
1 0 1 1 1
2 0 0 1 1
A3 0
3 0 0 0
4 1 1 1 1
1 1 1 1 1
2 1 1 1 1
A4 0
3 0 0 0
4 1 1 1 1
165
Note that accor di n g to the algorit h m vert ex 3 is not reac h a bl e from itself
1. This is beca u s e as can be seen in the gra p h, ther e is no path from
vert ex 3 back to itself.
7. 6. 3 . Traver s i n g a Grap h:
Many graph algorithms require one to systematically examine the nodes and edges of a graph G.
There are two standard ways to do this. They are:
During the execu tion of thes e algorit h m s , each node N of G will be in one
of thre e stat e s , called the statu s of N, as follows:
Both BFS and DFS impos e a tree (the BFS/DFS tree) on the struc t u r e of
gra p h. So, we can comp u t e a span ni n g tree in a gra p h. The comp u t e d
span ni n g tree is not a minim u m spa n ni n g tre e. The span ni n g tree s
obtain e d using dept h first sea rc h e s are called dept h first spa n ni n g tree s .
The spa n nin g tree s obtain e d using bre a d t h first sea r c h e s are called
Brea d t h first spa n ni n g tre e s.
The gen e r al idea behin d a bre a d t h first trave r s a l beginni n g at a sta rti n g
node A is as follows. First we exami n e the starti n g node A. Then we
exa mi n e all the neigh b o r s of A. Then we exa min e all the neigh b o r s of
neigh b o r s of A. And so on. We nee d to keep track of the neigh b o r s of a
node, and we nee d to gua r a n t e e that no node is proce s s e d more tha n
once. This is accom plis h e d by using a QUEUE to hold node s that are
waiting to be proce s s e d , and by using a field STATUS that tells us the
curr e n t stat u s of any node. The span ni n g tree s obtain e d using BFS are
called Brea d t h first spa n ni n g tree s.
2. Put the sta rti n g node A in QUEUE and chan g e its stat u s to the
waiting stat e (STATUS = 2).
166
3. Repe a t the following steps until QUEUE is empty:
4. Exit.
2. Push the starti n g node A into STACK and chan g e its stat u s to the
waiting stat e (STATUS = 2).
a. Pop the top node N from STACK. Proce s s N and chan g e the
stat u s of N to the proc e s s e d stat e (STATUS = 3).
Example 1:
Consider the graph shown below. Traverse the graph shown below in breadth first order and depth
first order.
167
No d Adja c e n c y
A
e Lis t
A F, C, B
F C B
B A, C, G
A, B, D, E, F,
C
G
D E G D C, F, E, J
E C, D, G, J, K
J K
F A, C, D
G B, C, E, K
A Gr a p h G
J D, E, K
K Adjace n cy
E,listG,forJgra p h G
Curr e Stat u s
Proce s s e d
nt QUEUE
Nodes A B C D E F G J K
Node
1 1 1 1 1 1 1 1 1
A 2 1 1 1 1 1 1 1 1
A F C B A 3 2 2 1 1 2 1 1 1
F C BD AF 3 2 2 2 1 3 1 1 1
BDE
C AF C 3 2 3 2 2 3 2 1 1
G
B D E G A F C B 3 3 3 2 2 3 2 1 1
D E GJ A F C BD 3 3 3 3 2 3 2 2 1
E GJK A F C BD E 3 3 3 3 3 3 2 2 2
G JK A F C BD E G 3 3 3 3 3 3 3 2 2
J K A F C BD E GJ 3 3 3 3 3 3 3 3 2
A F C B D E G J
K EMPTY 3 3 3 3 3 3 3 3 3
K
For the above graph the Breadth first traversal sequence is: A F C B D E G J K.
Curr e Stat u s
Proce s s e d
nt Stack
Node s A B C D E F G J K
Node
1 1 1 1 1 1 1 1 1
A 2 1 1 1 1 1 1 1 1
A BC F A 3 2 2 1 1 2 1 1 1
F BC D AF 3 2 2 2 1 3 1 1 1
168
D BC E J AF D 3 2 2 3 2 3 1 2 1
J B C E AF DJ
3 2 2 3 2 3 1 3 2
K
K B C E AF DJK
3 2 2 3 2 3 2 3 3
G
G BC E A F DJKG 3 2 2 3 2 3 3 3 3
E BC A F DJKGE 3 2 2 3 3 3 3 3 3
C B A F DJKGE C 3 2 3 3 3 3 3 3 3
B EMPTY A F D JK G E C
3 3 3 3 3 3 3 3 3
B
For the above graph the Depth first traversal sequence is: A F D J K G E C B.
Exa m p l e 2:
Traverse the graph shown below in breadth first order, depth first order and construct the breadth first
and depth first spanning trees.
Node Adjacency List
A H I A F, B, C, G
B A
B C G C A, G
D E, F
J K
E G, D, F
D F A, E, D
E G A, L, E, H, J, C
F
H G, I
L M
The Gr aph G I H
J G, L, K, M
K J
L G,listJ,forMthe gra p h G
The adjac e n cy
M L, J
If the dept h first trave r s a l is initiat e d from vertex A, the n the vertice s of
gra p h G are visited in the orde r: A F E D G L J K M H I C B . The dept h
first span ni n g tree is show n in the figure given below:
F B
G D
L H C
J I
K M
D e p t h f ir s t T r a v e r s a l
169
If the brea d t h first trave r s a l is initiat e d from vert ex A, the n the vertic e s
of gra p h G are visited in the orde r: A F B C G E D L H J M I K . The
bre a d t h first spa n ni n g tree is show n in the figur e given below:
F B C G
E D L H J
M I K
B r e a d t h f ir s t t r a v e r s a l
Exa m p l e 3:
Traverse the graph shown below in breadth first order, depth first order and construct the breadth first
and depth first spanning trees.
2 3
4 5 6 7
Gr a p h G
Vert e x
1 2 3
2 1 4 5
3 1 6 7
4 2 8
5 2 8
6 3 8
7 3 8
8 4 5 6 7
Adj ac e nc y list f o r g r a p h G
If the dept h first is initiat e d from vert ex 1, the n the vertic e s of gra p h G
are visite d in the orde r: 1, 2, 4, 8, 5, 6, 3, 7. The dept h first spa n ni n g tree
is as follows:
170
1
2 3
4 5 6 7
D e p t h F ir s t S p a n n i n g T r e e
If the brea d t h first sea rc h is initiat e d from vert ex 1, then the vertice s of
G are visited in the orde r: 1, 2, 3, 4, 5, 6, 7, 8. The bre a d t h first spa n ni n g
tre e is as follows:
2 3
4 5 6 7
B r e a d t h F ir s t S p a n n i n g T r e e
171
Conv e r t i n g a m- ary tre e (g e n e r a l tre e ) to a bin ary tre e:
Ther e is a one- to- one mappi n g betw e e n gene r a l orde r e d tre e s and binary
tre e s. So, every tree can be uniqu ely rep r e s e n t e d by a binary tree.
Furt h e r m o r e , a fores t can also be rep r e s e n t e d by a bina ry tre e.
Conver sio n from gene r a l tree to bina ry can be done in two stag e s .
Once this is done then for any partic ula r node, we choos e its left
and right sons in the following man n e r :
Example 1:
Convert (Encoding m-ary trees as binary trees) the following ordered tree into a binary tree.
2 3 4 5
6 7 8 9 10 11
Solution:
2 3 4 5
6 7 8 9 10 11
172
1
6 3
7 8 4
10
11
Exa m p l e 2:
1 7
2 3 8 9 10
4 5 6 11 12 13
0
Solution:
1 7
2 3 8 9 10
4 5 6 11 12 13
Stage 2 tree using the above mentioned procedure is as follows (binary tree representation of forest):
173
1
2 7
4 3 8
5 6 11 9
9
10
12
13
Dep t h firs t se ar c h :
In Dept h first sea rc h , we begin with root as a start stat e, the n som e
succ e s s o r of the star t stat e, the n som e succe s s o r of that stat e, then some
succ e s s o r of that and so on, trying to reac h a goal stat e. One simple way
to imple m e n t dept h first sea rc h is to use a stack dat a struc t u r e
consis ti n g of root node as a start stat e.
If dept h first sea rc h reac h e s a stat e S witho u t succ e s s o r s , or if all the
succ e s s o r s of a stat e S have bee n chos e n (visite d) and a goal stat e has
not get bee n found, the n it “backs up” that mea n s it goes to the
imm e di a t ely previou s stat e or pred e c e s s o r form ally, the stat e whos e
succ e s s o r was ‘S’ originally.
A
E
S T A RT J
S B
H G GOA L
C F
K
I
Suppos e S is the star t and G is the only goal stat e. Dept h first sea r c h will
174
first visit S, then A, then D. But D has no succ e s s o r s , so we mus t back up
to A and try its secon d succ e s s o r , E. But this does n’t have any succ e s s o r s
eithe r, so we back up to A again. But now we have tried all the
succ e s s o r s of A and have n’t found the goal stat e G so we mus t back to
‘S’. Now ‘S’ has a secon d succe s s o r , B. But B has no succ e s s o r s , so we
back up to S again and choos e its third succe s s o r , C. C has one
succ e s s o r , F. The first succ e s s o r of F is H, and the first of H is J. J does n’t
have any succ e s s o r s , so we back up to H and try its secon d succe s s o r .
And that’s G, the only goal stat e.
Disadv a n t a g e s :
1. It works very fine whe n sea rc h grap h s are tree s or lattice s, but
can get struc k in an infinite loop on gra p h s . This is bec a u s e
dept h first sear c h can travel arou n d a cycle in the gra p h
foreve r.
Bre a d t h first se ar c h :
Breadth-first search starts at root node S and “discovers" which vertices are reachable from S.
Breadth-first search discovers vertices in increasing order of distance. Breadth-first search is named
because it visits vertices across the entire breadth.
A
E
S T A RT J
S B
H G GOA L
C F
K
I
Brea d t h first sea rc h finds stat e s level by level. Her e we first check all the
imm e di a t e succe s s o r s of the sta rt stat e. Then all the imme di a t e
succ e s s o r s of thes e , the n all the imme di a t e succe s s o r s of thes e, and so
on until we find a goal node. Suppo s e S is the start stat e and G is the
goal stat e. In the figure, star t stat e S is at level 0; A, B and C are at level
1; D, e and F at level 2; H and I at level 3; and J, G and K at level 4.
175
So brea d t h first sea rc h , will consid e r in orde r S, A, B, C, D, E, F, H, I, J
and G and then stop beca u s e it has reac h e d the goal node.
Brea d t h first sea rc h does not have the dang e r of infinite loops as we
consid e r stat e s in orde r of incre a s i n g num b e r of bra n c h e s (level) from
the start stat e.
One simple way to imple m e n t brea d t h first sear c h is to use a que u e dat a
stru c t u r e consistin g of just a star t stat e.
0 0 0 5
0 2 0 0
A 1 3 0 0
0 0 4 0
(3, 1) 1
(2, 2) 2
S= (3, 2) 3
(4, 3) 4
(1, 4) 5
The printed output lists the non-zero elements of S, together with their row and
column indices. The elements are sorted by columns, reflecting the internal data
structure.
/* Check whet h e r the given matrix is spa r s e mat rix or not, if so then
print in alter n a t iv e form for stor a g e . */
176
main()
{
int mat rix[20][2 0], m, n, total_ele m e n t s , total_zero s = 0, i, j;
clrsc r();
printf("\n Ente r Num b e r of rows and colum n s : ");
scanf("%d %d",&m, &n);
total_ele m e n t s = m * n;
printf("\n Ente r data for spa r s e mat rix: ");
for(i = 0; i < m ; i+ + )
{
for( j = 0; j < n ; j+ + )
{
scanf("%d", &mat rix[i][j]);
if( mat rix[i][j] = = 0)
{
total_zero s + + ;
}
}
}
if(tot al_ze r o s > total_ele m e n t s / 2 )
{
printf("\n Given Mat rix is Spar s e Mat rix..");
printf("\n The Repr e s e n t a i o n of Spa rs e Matrix is: \n");
printf("\n Row \t Col \t Value ");
for(i = 0; i < m ; i+ + )
{
for( j = 0; j < n ; j+ + )
{
if( mat rix[i][j] != 0)
{
printf("\n %d \t %d \t %d",i,j,ma t rix[i][j]);
}
}
}
}
else
printf("\n Given Mat rix is Not a Spa r s e Matrix..");
}
177
LECTURE NOTE S
on
DATA STRUCT U RE S
20 1 8 – 20 1 9
I B. Tec h II Se m e s t e r (R1 7 )
Mr. K Mun iv ar a Pras a d , Ass o c i a t e Prof e s s o r