You are on page 1of 166

UNIT-I

PROGRAM M I N G PERFOR MA N CE

Perf o r m a n c e of a pr o g r a m : The perfor m a n c e of a progra m is


meas u r e d base d on the amou n t of com p u t e r me m o r y and time nee d e d
to run a progra m .

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:

1. Anal y t i c a l m e t h o d à called the Perfor m a n c e Analysis.


2. Exp e r i m e n t a l m e t h o d à called the Perfor m a n c e Meas u r e m e n t .

SPACE COMPLEXITY

Sp a c e co m p l e x i t y : The Spac e com pl e xi t y of a progra m is define d as


the amou n t of me m o r y it need s to run to com pl e tio n.

As said above the spac e complexity is one of the factor which


accou n t s for the perfor m a n c e of the progr a m . The spac e complexity can
be mea s u r e d using expe ri m e n t a l met ho d, which is done by run ni n g the
progr a m and then meas u r i n g the actu al spac e occupie d by the progr a m
durin g execu tio n. But this is done very rarely. We estim a t e the spac e
compl exity of the prog r a m before run nin g the prog r a m .

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 :

The prog r a m which is writt e n by the use r is the sourc e prog r a m .


When this prog r a m is compile d, a compile d version of the prog r a m is
gene r a t e d . For executi n g the prog r a m an execu t a bl e version of the
progr a m is gen e r a t e d . The spac e occupi e d by thes e thre e when the
progr a m is und e r execu tio n, will accou n t for the instr u c tio n spac e.

(ii) Dat a sp a c e :

The spac e nee d e d by the cons t a n t s , simple varia bl e s , arr ays ,


stru c t u r e s and othe r dat a struc t u r e s will accou n t for the data spac e.

The Data space depe n d s on the followin g factors:

 Str uc t u r e size – It is the sum of the size of compo n e n t


variabl e s of the struc t u r e .
 Array size – Total size of the array is the prod u c t of the size
of the dat a type and the num b e r of array locations.

2
(iii) Envir o n m e n t st a c k spa c e :

The Environ m e n t stack spac e is used for saving infor m a ti o n need e d


to res u m e exec utio n of partially comple t e d function s. That is when e v e r
the cont rol of the prog r a m is tran sfe r r e d from one function to anot h e r
durin g a function call, then the values of the local variable of that
function and retu r n add r e s s are stor e d in the environ m e n t stack. This
inform a tio n is retriev e d whe n the contr ol come s back to the sam e
function.

The environ m e n t stac k space dep e n d s on the followin g factors:

 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

c à Fixed spac e or const a n t spac e


S p à Variable spac e

We will be inter e s t e d in estim a ti n g only the varia bl e spac e bec a u s e that


is the one which varies accor din g to the user input.
TIME COMPLEXITY

Ti m e co m p l e x i t y : Tim e com pl e xit y of the progra m is define d as the


amou n t of com p u t e r tim e it nee d s to run to com ple tio n.

The time complexity can be mea s u r e d , by mea s u ri n g the time


take n by the prog r a m whe n it is execu t e d . This is an expe ri m e n t a l
met h o d. But this is done very rarely. We always try to estim a t e the time
cons u m e d by the prog r a m even before it is run for the first time.

The tim e com ple xit y of the progra m depe n d s on the followin g
factors:

 Com piler used – some compile r s prod u c e optimize d code


which cons u m e s less time to get execu t e d .
 Com piler options – The optimiza tion options can be set in the
options of the compile r.
 Targe t com p u t e r – The spee d of the comp u t e r or the num b e r
of instr u c tio n s execu t e d per secon d differs from one
comp u t e r to anot h e r.

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.

(ii) Run tim e or Exe c u t i o n ti m e - The time take n for the


execu tion of the progr a m . The optimiz e d code will take less
time to get exec ut e d .

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

We will be inte r e s t e d in estim a ti n g only the executio n time as this is the


one which varies accor di n g to the user input.

Esti m a t i n g th e Exec u t i o n tim e:

Pro g r a m st e p : Progra m step is a mea nin g f ul seg m e n t of a progra m


whic h is inde p e n d e n t of instan c e charact eris tic s. Instan c e
charac t eris tic s are the variables whos e values are decid e d by the user
input at that instant of tim e.

Ste p s in esti m a ti n g the exec u tio n tim e of progra m:

(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).

The various asym p t o ti c nota tio n s are:

(i) O ( Big Oh notation )

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

Let us take g(n) = n


c = 4
n0 = 2

Let us check the above condition

3n + 1 ≤ 4n for all n ≥ 2

The condition is satisfied. Henc e f(n) = O(n).

2. f(n) = 10n 2 + 4n + 2

Let us take g(n) = n 2


c = 11
n0 = 6

Let us check the above condition

10n 2 + 4n + 2 ≤ 11n for all n ≥ 6

The condition is satisfied. Henc e f(n) = O(n 2 ).

Ω - Ome g a nota tion

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

Let us take g(n) = n


c = 3
n0 = 0

5
Let us check the above condition

3n + 1 ≥ 3n for all n ≥ 0

The condition is satisfied. Henc e f(n) = Ω(n).

2. f(n) = 10n 2 + 4n + 2

Let us take g(n) = n 2


c = 10
n0 = 0

Let us check the above condition

10n 2 + 4n + 2 ≥ 10n for all n ≥ 0

The condition is satisfied. Henc e f(n) = Ω(n 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 .

We have seen in the previou s two case s,

3n + 2 = O(n) and 3n + 2 = Ω(n)

Henc e we can write 3n + 2 = θ(n)

o - Littl e Oh not a t i o n

f(n) = o(g(n)) if and only if f(n) = O(g(n)) and f(n) ≠ Ω(g(n))

For exa m pl e,

3n + 2 = O(n 2 ) but 3n + 2 ≠ Ω(n 2 )

Ther efo r e it can be writt e n as 3n + 2 = o(n 2 )

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:

1. Linear or sequential search


2. Binary search

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.

The time complexity of linear search is O(n).

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

If we are searching for: 45, we’ll look at 1 element before success


39, we’ll look at 2 elements before success
8, we’ll look at 3 elements before success
54, we’ll look at 4 elements before success
77, we’ll look at 5 elements before success
38 we’ll look at 6 elements before success
24, we’ll look at 7 elements before success
16, we’ll look at 8 elements before success
4, we’ll look at 9 elements before success
7, we’ll look at 10 elements before success
9, we’ll look at 11 elements before success
20, we’ll look at 12 elements before success

For any element not in the list, we’ll look at 12 elements before failure

Example 2:

Let us illustrate linear search on the following 9 elements:

Index 0 1 2 3 4 5 6 7 8
Elements -15 -6 0 7 9 23 54 82 101

Searching different elements is as follows:

1. Searching for x = 7 Search successful, data found at 3rd position

2. Searching for x = 82 Search successful, data found at 7th position

3. Searching for x = 42 Search un-successful, data not found

A non-recursive program for Linear Search:

# 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
}

A Recursive program for linear search:

# include <stdio.h>
# include <conio.h>

void linear_search(int a[], int data, int position, int n)


{
int mid;
if(position < n)
{
if(a[position] == data)
printf("\n Data Found at %d ", position);
else
linear_search(a, data, position + 1, n);
}
else
printf("\n Data not found");
}

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:

Let us illustrate binary search on the following 12 elements:

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

If we are searching for x = 7: (This needs 4 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
low = 2, high = 2, mid = 4/2 = 2, check 7, found

If we are searching for x = 8: (This needs 2 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 1, high = 5, mid = 6/2 = 3, check 8, found

If we are searching for x = 9: (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 = 4, high = 5, mid = 9/2 = 4, check 9, found

If we are searching for x = 16: (This needs 4 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 1, high = 5, mid = 6/2 = 3, check 8
low = 4, high = 5, mid = 9/2 = 4, check 9
low = 5, high = 5, mid = 10/2 = 5, check 16, found

If we are searching for x = 20: (This needs 1 comparison)


low = 1, high = 12, mid = 13/2 = 6, check 20, found

If we are searching for x = 24: (This needs 4 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39
low = 7, high = 10, mid = 17/2 = 8, check 38

10
low = 7, high = 7, mid = 14/2 = 7, check 24, found

If we are searching for x = 38: (This needs 3 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39
low = 7, high = 10, mid = 17/2 = 8, check 38, found

If we are searching for x = 39: (This needs 2 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39, found

If we are searching for x = 45: (This needs 4 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39
low = 10, high = 12, mid = 22/2 = 11, check 54
low = 10, high = 10, mid = 20/2 = 10, check 45, found

If we are searching for x = 54: (This needs 3 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39
low = 10, high = 12, mid = 22/2 = 11, check 54, found

If we are searching for x = 77: (This needs 4 comparisons)


low = 1, high = 12, mid = 13/2 = 6, check 20
low = 7, high = 12, mid = 19/2 = 9, check 39
low = 10, high = 12, mid = 22/2 = 11, check 54
low = 12, high = 12, mid = 24/2 = 12, check 77, found
The number of comparisons necessary by search element:

20 – requires 1 comparison; 8 and 39 – requires 2 comparisons;


4, 9, 38, 54 – requires 3 comparisons; and 7, 16, 24, 45, 77 – requires 4 comparisons

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:

Let us illustrate binary search on the following 9 elements:

Index 1 2 3 4 5 6 7 8 9
Elements -15 -6 0 7 9 23 54 82 101

The number of comparisons required for searching different elements is as follows:


1. If we are searching for x = 101: (Number of comparisons = 4)

low high mid


1 9 5
6 9 7
8 9 8
9 9 9
found

2. Searching for x = 82: (Number of comparisons = 3)

low high mid


1 9 5
6 9 7
8 9 8
found

3. Searching for x = 42: (Number of comparisons = 4)

11
low high mid
1 9 5
6 9 7
5 6 5
6 6 6
7 6 not found

4. Searching for x = -14: (Number of comparisons = 3)

low high mid


1 9 5
4 4 2
1 1 1
2 1 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 ");
}

A recursive program for binary search:

# include <stdio.h>
# include <conio.h>

void bin_search(int a[], int data, int low, int high)


{
int mid ;
if( low <= high)
{
mid = (low + high)/2;
if(a[mid] == data)
printf("\n Element found at location: %d ", mid + 1);
else
{
if(data < a[mid])
bin_search(a, data, low, mid-1);
else
bin_search(a, data, mid+1, high);
}
}
else
printf("\n Element not found");
}

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.

Consider the array x[n] which is stored in memory as shown below:

X[0] X[1] X[2] X[3] X[4] X[5]


33 44 22 11 66 55

Suppose we want our array to be stored in ascending order. Then we pass through the array 5 times
as described below:

Pass 1: (first element is compared with all other elements)

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:

X[0] X[1] X[2] X[3] X[4] X[5] Remarks


33 44 22 11 66 55
22 44
11 44
44 66
55 66
33 22 11 44 55 66

The biggest number 66 is moved to (bubbled up) the right most position in the array.

Pass 2: (second element is compared)

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:

X[0] X[1] X[2] X[3] X[4] Remarks


33 22 11 44 55
22 33
11 33
33 44
44 55
22 11 33 44 55

The second biggest number 55 is moved now to X[4].

Pass 3: (third element is compared)

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].

X[0] X[1] X[2] X[3] Remarks


22 11 33 44
11 22

14
22 33
33 44
11 22 33 44

Pass 4: (fourth element is compared)

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].

X[0] X[1] X[2] Remarks


11 22 33
11 22
22 33

Pass 5: (fifth element is compared)

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.

For an array of size n, we required (n-1) passes.

Program for Bubble Sort:

#include <stdio.h>
#include <conio.h>

void bubblesort(int x[],int n)


{
int i, j, t;
for (i = 0; i < n; i++)
{
for (j = 0; j <n-i; j++)
{
if (x[j] > x[j+1])
{
t = x[j];
x[j] = x[j+1];
x[j+1] = t;
}
}
}
}

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

65 70 75 80 50 60 55 85 45 find the first smallest element

i j swap a[i] & a[j]

45 70 75 80 50 60 55 85 65 find the second smallest element

i j swap a[i] and a[j]

45 50 75 80 70 60 55 85 65 Find the third smallest element

i j swap a[i] and a[j]

16
45 50 55 80 70 60 75 85 65 Find the fourth smallest element

i j swap a[i] and a[j]

45 50 55 60 70 80 75 85 65 Find the fifth smallest element

i j swap a[i] and a[j]

45 50 55 60 65 80 75 85 70 Find the sixth smallest element

i j swap a[i] and a[j]

45 50 55 60 65 70 75 85 80 Find the seventh smallest element

i j swap a[i] and a[j]

45 50 55 60 65 70 75 85 80 Find the eighth smallest element

i J swap a[i] and a[j]

45 50 55 60 65 70 75 80 85 The outer loop ends.

Non-recursive Program for selection sort:

# include<stdio.h>
# include<conio.h>

void selectionSort( int low, int high );

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;
}

void selectionSort( int low, int high )


{
int i=0, j=0, temp=0, minindex;
for( i=low; i <= high; i++ )
{
minindex = i;
for( j=i+1; j <= high; j++ )
if( a[j] < a[minindex] )
minindex = j;
temp = a[i];
a[i] = a[minindex];
a[minindex] = temp;
}
}

Recursive Program for selection sort:

#include <stdio.h>

17
#include<conio.h>

int x[6] = {77, 33, 44, 11, 66};

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)

// A is the arr ay cont ai ni n g the list of dat a items


// N is the num b e r of data items in the list

Last ß N – 1

Repe a t For Pass = 1 to Last Step 1


Repe a t For I = 0 to Pass – 1 Step 1
If A[Pass] < A[I]
Then
Temp ß A[Pass]
Repe a t For J = Pass -1 to I Step -1
A[J +1] ß A[J]
End Repe a t
A[I] ß Temp
End If
End Repe a t
End Repe a t

End INSERTION S ORT

In Inser tio n Sort algorit h m , Last is mad e to point to the last


elem e n t in the list and Pass is mad e to point to the secon d elem e n t in the
list. In every pass the Pass is incre m e n t e d to point to the next elem e n t
and is contin u e d till it reac h e s the last elem e n t . During eac h pas s
A[Pass] is comp a r e d all elem e n t s before it. If A[Pass] is lesse r than A[I]
in the list, then A[Pass] is inser t e d in position I. Finally, a sort e d list is
obtain e d.
For perfor mi n g the inser tion oper a tio n, a variable tem p is used to
safely store A[Pass] in it and the n shift right elem e n t s star tin g from A[I]
to A[Pass- 1].

Exa m p l e :

N = 10 à Num b e r of elem e n t s in the list


L à Last
P à Pass

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 :

void arr ay::so r t()


{
int tem p, last = c o u n t- 1;
for (int pas s = 1 ; pass < = l a s t ; p a s s + + )
{
for (int i=0; i<p a s s; i+ + )
{

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.

3. If down > up, interchange a[down] with a[up]

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);
}

interchange(a, up, down)


{
p = a[up];
a[up] = a[down];
a[down] = p;
}

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

Program for Quick Sort (Recursive version):

# include<stdio.h>
# include<conio.h>

void quicksort(int, int);


int partition(int, int);
void interchange(int, int);

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);
}
}

int partition(int low, int high)


{
int pivot = array[low];
int up = low, down = high;

do
{
do
up = up + 1;
while(array[up] < pivot );

do
down = down - 1;
while(array[down] > pivot);

if(up < down)


interchange(up, down);

}while(up < down);

25
array[low] = array[down];
array[down] = pivot;
return down;
}

void interchange(int i, int j)


{
int temp;
temp = array[i];
array[i] = array[j];
array[j] = temp;
}

Heap and Heap Sort

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.

Max and Min Heap data structures:

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.

Representation of Heap Tree:

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 root of the tree is in location 1.


 The left child of an element stored at location i can be found in location 2*i.
 The right child of an element stored at location i can be found in location 2*i+1.
 The parent of an element stored at location i can be found at location floor(i/2).

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:

X[1] X[2] X[3] X[4] X[5] X[6] X[7] X[8]


65 45 60 40 25 50 55 30

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

Operations on heap tree:

The major operations required to be performed on a heap tree:

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:

1. Build a heap tree with the given set of data.


2. a. Remove the top most item (the largest) and replace it with the last
element in the heap.
b. Re-heapify the complete binary tree.
c. Place the deleted node in the output.
3. Continue step 2 until the heap tree is empty.

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

Program for Heap Sort:

33
# include <stdio.h>
# include <conio.h>

void adjust(int i, int n, int a[])


{
int j, item;
j = 2 * i;
item = a[i];
while(j <= n)
{
if((j < n) && (a[j] < a[j+1]))
j++;
if(item >= a[j])
break;
else
{
a[j/2] = a[j];
j = 2*j;
}
}
a[j/2] = item;
}

void heapify(int n, int a[])


{
int i;
for(i = n/2; i > 0; i--)
adjust(i, n, a);
}

void heapsort(int n,int a[])


{
int temp, i;
heapify(n, a);
for(i = n; i > 0; i--)
{
temp = a[i];
a[i] = a[1];
a[1] = temp;
adjust(1, i - 1, a);
}
}

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.

Given a sequ e n c e of n elem e n t s A[1], ….A[N], the gene r a l idea is to


imagin e the m split into two sets A[1],…A[N/2] and A[(N/2) + 1],…A[N].
Each set is individu ally sort e d, and the res ultin g sort e d sequ e n c e s are
mer g e d to prod u c e a single sort e d sequ e n c e of N elem e n t s . Thus this
sortin g meth o d follows Divide and Conqu e r stra t e g y.

Alg o r i t h m :

Proc e d u r e MERGE(A, low, mid , hig h )

// A is the arr ay cont ai ni n g the list of dat a items

I ß low, J ß mid + 1 , K ß low


While I ≤ mid and J ≤ high
If A[I] < A[J]
Then
Temp[K] ß A[I]
IßI+ 1
K ß K+1
Else
Temp[K] ß A[J]
JßJ+ 1
KßK+ 1
End If
End While

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

Repe a t for K = low to high step 1


A[K] ß Temp[K]
End Repe a t
End MERGE

35
Proc e d u r e MERGE SO RT (A, low, hig h )

// A is the arr ay cont ai ni n g the list of dat a items

If low < high


Then
mid ß (low + high)/2
MERGESORT(low, high)
MERGESORT(mid + 1, high)
MERGE(low, mid, high)
End If
End MERGESORT

The first algorit h m MERGE can be applie d on two sort e d lists to


mer g e the m. Initially, the index varia ble I points to low and J points to
mid + 1. A[I] is comp a r e d with A[J] and if A[I] found to be lesse r than
A[J] then A[I] is store d in a temp o r a r y array and I is incre m e n t e d
othe r wi s e A[J] is store d in the tem po r a r y arr ay and J is incre m e n t e d .
This comp a ri s o n is contin u e d until eithe r I cross e s mid or J cross e s high.
If I cross e s the mid first then that implies that all the elem e n t s in first list
is acco m m o d a t e d in the tem po r a r y array and henc e the rem ai ni n g
elem e n t s in the secon d list can be put into the tem po r a r y arr ay as it is. If
J cross e s the high first then the rem ai ni n g elem e n t s of first list is put as
it is in the tem po r a r y arr ay. After this proce s s we get a single sort e d list.
Since this met h o d mer g e s 2 lists at a time, this is called 2- way merg e
sort.

In the MERGESORT algorit h m , the given unsor t e d list is first split


into N num b e r of lists, eac h list consisti n g of only 1 elem e n t . Then the
MERGE algorit h m is applied for first 2 lists to get a single sort e d list.
Then the sam e thing is done on the next two lists and so on. This proc e s s
is contin u e d till a single sort e d list is obtain e d.

Exa m p l e :

Let L à low, M à mid, H à high

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 :

void arr ay::so r t(in t low, int high)


{
int mid;
if (low < h i g h )
{
mid = (lo w + h i g h )/ 2;
sort(low, mi d);
sort(mi d + 1 , high);
mer g e(low, mid, high);
}
}

void arr ay:: m e r g e (i n t low, int mid, int high)


{
int i=low, j= mid + 1 , k=low, temp[ MAX];

while (i< = m i d && j< = h i g h )


if (a[i] < a[j])
tem p[k + + ] = a [ i + + ] ;
else
tem p[k + + ] = a [ j + + ] ;

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 :

1. Very useful for sorting bigge r lists.


2. Applicable for exte r n a l sortin g also.

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

Comp a r e the elem e n t s at a gap of 4. i.e 18 with 38 and so on and swap if


first num b e r is gre a t e r than secon d.

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.

After inser tion sort. The final array is sort e d.

39
UNIT- II
STACKS

The dat a stru c t u r e s seen so far, allows insertio n and deletion of


elem e n t s at any place. But som e ti m e s it is req ui r e d to per mit the
addition and deletion of elem e n t s only at one end that is eithe r at the
beginni n g or at the end.

Sta c k s : A stack is a data struct u r e in whic h addition of new ele m e n t


or deletion of an existin g ele m e n t always tak es place at the sam e end.
This end is often kno w n as top of stac k. Whe n an ite m is adde d to a
stack, the operation is called pus h, and whe n an ite m is rem ov e d from
the stack the operation is called pop. Stac k is also called as Last- In-
First- Out (LIFO) list.

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.

 Pu s h: Allows adding an ele m e n t at the top of the stack.


 Po p: Allows re mo vi n g an ele m e n t from the top of the stac k.

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.

ARRAY IMPLEME N TATIO N OF THE STACK

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 :

On deletion of elem e n t s the stack shrink s at the sam e end, as the


elem e n t s at the top get remove d.

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( )

If arr ay s are use d for imple m e n t i n g the stacks, it would be very


easy to man a g e the stacks. How ev e r, the proble m with an array is that
we are req ui r e d to declar e the size of the arr ay befor e using it in a
progr a m . This mea n s the size of the stack should be fixed. We can
decla r e the array with a maxim u m size large enou g h to man a g e a stack.
As res ult, the stack can grow or shrink within the spac e res e rv e d for it.
The following prog r a m imple m e n t s the stack using arr ay.

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 >

const int MAX=2 0;


class stack
{
privat e:
int a[MAX];
int top;
public:
stack();
void push(int x);
int pop();
void display();

};

stack::s t a c k()
{
top =- 1;
}

void stack::p u s h(in t x)


{
if (top = = M AX- 1)
{
cout < < " \ n S t a c k is full!";
ret u r n;
}
else
{
top + + ;
a[top] = x;
}
}

int stack::po p()


{
if (top = = - 1)
{
cout < < " \ n S t a c k is empty!";
ret u r n NULL;
}
else
{
int item = a [ t o p];
top- -;
ret u r n item;

42
}
}

void stack::dis pl ay()


{
int tem p = t o p ;
while (tem p! = - 1)
cout < < " \ n " < < a [ 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
30
20
10
Poppe d item: 4 0
Poppe d item: 3 0
20
10

LINKED LIST IMPLEME N TATIO N OF STACK

Initially, when the stack is empty, top points to NULL. When an


elem e n t is add e d using the pus h oper a tio n, top is mad e to point to the
lates t elem e n t which ev e r is add e d.

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

The dat a in the topmo s t node of the stack is first stor e d in a


variabl e called item. Then a tem p o r a r y point e r is cre a t e d to point to top.
The top is now safely moved to the next node below it in the stack. Temp
node is delet e d and the item is retu r n e d .

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( )

The following prog r a m imple m e n t s the stack using linke d lists.

Pro g r a m :

// Stack imple m e n t e d using linked list

#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 ;
}
}

void stack::p u s h(in t x)


{
node *temp;

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 ;
}

int stack::po p()


{
if (top = = N U L L)
{
cout < < " \ n S t a c k is empty!";
ret u r n NULL;
}
node *temp = t o p ;
int item = t e m p - > d a t a ;
top = t e m p - >link;
delet e tem p;
ret u r n item;
}

void stack::dis pl ay()


{
node *temp = t o p ;
while (tem p! = N U LL)
{
cout < < " \ n " < < t e m p - > d a t a ;
tem p = t e m p - >link;
}
}

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

Conv e r s i o n of Infix Expr e s s i o n to Pos tf ix Expre s s i o n

The stack s are frequ e n t ly used in evalua tio n of arith m e t i c


expre s sio n s . An arith m e t ic expre s sio n consist s of oper a n d s and
oper a t o r s . The oper a n d s can be num e ri c values or num e ric variable s.
The oper a t o r s used in an arith m e t i c expre s sio n repr e s e n t the oper a tio n s
like addition, subt r a c ti o n, multiplica tio n, division and expon e n t i a tio n.

The arith m e t ic expre s s io n expr e s s e d in its norm al form is said to


be Infix nota tion, as show n:

A+ B

The above expr e s s io n in prefix form would be repr e s e n t e d as follows:

+ AB

The sam e expr e s sio n in postfix form would be repr e s e n t e d as follows:

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.

The function to conver t an expre s sio n from infix to postfix consis ts


following step s:

1. Every char a c t e r of the expr e s si o n string is scan n e d in a while loop


until the end of the expr e s si o n is reac h e d .
2. Following step s are perfor m e d depe n di n g on the type of char a c t e r
scan n e d .
(a) If the cha r a c t e r scan n e d happ e n s to be a spac e then that
char a c t e r is skipp e d.
(b) If the cha r a c t e r scan n e d is a digit or an alph a b e t , it is add e d
to the targ e t strin g point e d to by t.
(c) If the cha r a c t e r scan n e d is a closing par e n t h e s i s then it is
add e d to the stack by calling pus h( ) function.
(d) If the cha r a c t e r scan n e d happ e n s to be an oper a t o r, then
firstly, the topm os t elem e n t from the stack is ret rieve d .
Throu g h a while loop, the priorities of the cha r a c t e r scan n e d

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 :

// Progr a m to conver t an Infix form to Postfix form

#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 >

const int MAX=5 0;

class infix
{
privat e:

char targ e t[ MAX], stack[MAX];


char *s, *t;
int top;

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
}

void infix::pus h(c h a r c)


{
if (top = = M AX- 1)
cout < < " \ n S t a c k is full\n!";
else
{
top + + ;
stack[to p] = c ;
}
}

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+ + ;
}

if (*s = = ' ) ')


{
opr = p o p ();
while ((opr)! = ' (')
{
*t=o p r;
t+ + ;
opr = p o p ();
}
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 infix::sho w()


{
cout < < t a r g e t ;
}

void main()
{
clrsc r();
char expr[MAX], *res[MAX];
infix q;

cout < < " \ n E n t e r an expr e s sio n in infix form: ";


cin > > e x p r ;
q.conve r t( ex p r );

cout < < " \ n T h e postfix expr e s s io n is: ";


q.sho w();
getch();
}

Ou t p u t :

Ente r an expre s sio n in infix form: 5 ^ 2- 5

Stack is empty

The postfix expr e s sio n is: 52 ^ 5 -

Evalu a t i o n of Expr e s s i o n en t e r e d in pos tf ix for m

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 :

// Progr a m to evalu a t e an expr e s sio n ente r e d in postfix form

#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 >

const int MAX=5 0;

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;
}

void postfix::pus h(in t item)


{
if (top = = M AX- 1)
cout < < e n d l < < " S t a c k is full";
else
{
top + + ;
stack[to p] = i t e m ;
}
}

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

Qu e u e : Queu e is a linear data struct u r e that per mi t s insertion of ne w


ele m e n t at one end and deletion of an ele m e n t at the other end. The
end at which the deletion of an ele m e n t take place is called front, and
the end at which insertion of a new ele m e n t can take place is called
rear. The deletion or insertion of ele m e n t s can take place only at the
front or rear end of the list respe c tiv ely.

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.

ARRAY IMPLEME N TATIO N OF QUEUE

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

Ther e are two com mo n oper a ti o n s one in a queu e . They are


addition of an elem e n t to the queu e and deletion of an elem e n t from the
queu e . Two variable s front and rea r are use d to point to the ends of the
queu e . The front point s to the front end of the que u e wher e deletion
takes plac e and rea r point s to the rea r end of the que u e, wher e the

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 :

// Queu e s and various oper a tio n s on it – Using arr ays

#i n cl u d e <ios t r e a m . h >
#i n cl u d e <co nio. h >

const int MAX=1 0;


class que u e
{
privat e:
int a[MAX], front, rea r;
public:
queu e();
void addq(int x);
int delq();
void display();
};

queu e:: q u e u e ()
{
front = r e a r = - 1;
}

void que u e:: a d d q (i n t x)


{
if (rea r = = M AX- 1)
{
cout < < " Q u e u e is full!";
ret u r n;
}
rea r + + ;
a[re a r] = x ;
if (front = = - 1)
front = 0 ;
}

int que u e::d el q()

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 que u e:: dis pl ay()


{
if (front = = - 1)
ret u r n;
for (int i=fron t; i< = r e a r ; i+ + )
cout < < a [ i ] < < " \ t ";
}

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 dis a d v a n t a g e s of array s are:

 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 .

 Inse r ti n g new elem e n t s at the front is pote n ti ally expe n sive


bec a u s e existing elem e n t s nee d to be shifted over to make
room.

 Deleting an elem e n t from an arr ay is not possible.

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 :

mall o c ( ) is a syste m function which allocat e s a block of memo ry in the


"hea p" and retu r n s a point e r to the new block. The prototy p e of malloc()
and othe r heap functions are in stdlib.h. malloc() retu r n s NULL if it
canno t fulfill the requ e s t . It is define d by:

void *malloc (number_of_bytes)

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.

Advan t a g e s of link e d list s :

Linked lists have many adva n t a g e s . Some of the very impor t a n t


adva n t a g e s are:

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 .

2. Linked lists have efficient memo ry utilization. Her e, mem o ry is


not pre- alloca t e d . Memo ry is alloca t e d whe n ev e r it is req ui r e d
and it is de- allocat e d (rem ove d) when it is no longe r nee d e d .

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.

Dis a d v a n t a g e s of link e d list s:

1. It cons u m e s more spac e beca u s e every node req uir e s a


addition al point e r to stor e addr e s s of the next node.

2. Sear c hi n g a partic ul a r elem e n t in list is difficult and also time


cons u m i n g .

Type s of Link e d List s:

Basically we can put linked lists into the following four item s:

1. Single Linke d List.


2. Double Linke d List.

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 .

Com p a r i s o n betw e e n array and lin k e d list:

ARRAY LINKED LIST


Size of an array is fixed Size of a list is not fixed
Memo ry is allocat e d from stack Memo ry is allocat e d from heap
It is nece s s a r y to specify the It is not nece s s a r y to specify the
num b e r of elem e n t s during num b e r of elem e n t s during
decla r a ti o n (i.e., during compile decla r a ti o n (i.e., memo ry is
time). alloca t e d durin g run time).
It occupie s less mem o ry than a
linked list for the sam e num b e r It occupie s more memo ry.
of elem e n t s .
Inse r ti n g new elem e n t s at the
front is pote n ti ally expe n sive Inse r ti n g a new elem e n t at any
bec a u s e existing elem e n t s nee d position can be carrie d out easily.
to be shifted over to make room.
Deleting an elem e n t from an
Deleting an elem e n t is possible.
arr ay is not possible.

Appli c a t i o n s of link e d list:

1. Linked lists are used to rep r e s e n t and manip ul a t e polyno mi al.


Polyno mi als are expr e s s io n cont ai ni n g ter m s with non zero
coefficien t and expon e n t s . For exam pl e:

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.

3. Linked lists are to imple m e n t stack, que u e , tree s and gra p h s .

4. Imple m e n t the symbol table in compiler const r u c t io n

6. 2. Sin g l e Link e d List:

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 .

The start point e r is an ordin a ry local point e r variable, so it is draw n


sepa r a t e ly on the left top to show that it is in the stack. The list node s
are draw n on the right to show that they are allocat e d in the hea p.

Impl e m e n t a t i o n of Sin g l e Link e d List:

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):

 Crea ti n g a struc t u r e with one dat a item and a next point e r,


which will be pointin g to next node of the list. This is called as
self- refer e n ti al struc t u r e .

 Initialise the start point e r to be NULL.

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

The bas i c op e r a t i o n s in a sin g l e lin k e d list are:

 Crea tio n.
 Inse r tio n.
 Deletion.
 Traver si n g.

Creating a node for Single Linked List:

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

Creat i n g a Sin g l y Link e d List with ‘n’ nu m b e r of nod e s :

The following steps are to be followed to create ‘n’ number of nodes:

63
 Get the new node using get no d e ().

new no d e = getno d e();

 If the list is empty, assign new node as start.

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.

 The star t point e r is mad e to point the new node by


assignin g the addr e s s of the new node.

 Repe a t the above steps ‘n’ times.

Figur e 6.2.4 shows 4 item s in a single linked list stor e d at differ e n t


locations in memo ry.

st a rt
100

10 200 20 300 30 400 40 X


100 200 300 400

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:

 Inse r ti n g a node at the begin nin g.


 Inse r ti n g a node at the end.
 Inse r ti n g a node at inter m e d i a t e position.

Ins e r t i n g a nod e at th e be g i n n i n g :

The following steps are to be followe d to inser t a new node at the


beginni n g of the list:

 Get the new node using get no d e ().

new no d e = getno d e();

 If the list is empty then start = newnode.

 If the list is not empty, follow the steps given below:

new no d e -> next = star t;


start = newnode;

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

10 200 20 300 30 400 40 X


100 200 300 400

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:

 Get the new node using getnode()

newnode = getnode();

 If the list is empty then start = newnode.

 If the list is not empty follow the steps given below:

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

10 200 20 300 30 400 40 500


100 200 300 400

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 .

Ins e r t i n g a nod e at int e r m e d i a t e pos i t i o n :

The following steps are followed, to insert a new node in an intermediate position in the list:

 Get the new node using get no d e ().

new no d e = getno d e();

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.

 Store the star ti n g add r e s s (which is in star t point e r) in tem p and


prev pointe r s . Then trave r s e the temp point e r upto the specified
position followed by prev point e r .

 After reac hi n g the specified position, follow the step s given


below:

prev -> next = new no d e ;


new no d e -> next = tem p;

 Let the inte r m e d i a t e position be 3.

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

10 200 20 500 30 400 40 X


100 200 300 400

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.

 Deleting a node at the begin ni n g.


 Deleting a node at the end.
 Deleting a node at inter m e d i a t e position.

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:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

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

10 200 20 300 30 400 40 X


100 200 300 400
t e mp

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:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

tem p = prev = start;


while(te m p -> next != NULL)
{
prev = temp;
tem p = tem p -> next;
}
prev -> next = NULL;
free(t e m p );

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 .

Del e t i n g a nod e at Int er m e d i a t e pos i t i o n :

The following steps are followe d, to delet e a node from an inter m e d i a t e


position in the list (List must cont ai n more tha n two node).

 If list is empty then display ‘Empty List’ mess a g e

 If the list is not empty, follow the step s given below.

if(pos > 1 && pos < node c t r)


{
tem p = prev = start;
ctr = 1;
while(ct r < pos)
{
prev = temp;
tem p = tem p -> next;
ctr + + ;
}
prev -> next = tem p -> next;
free(t e m p );
printf("\n node delet e d..");
}
The function delet e_a t_mid(), is used for deletin g the inter m e d i a t e node
in the list.

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

10 300 20 300 30 400 40 X


100 200 300 400

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 .

Traver s a l and dis pl a yi n g a list (Left to Rig h t ):

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:

 Assign the add r e s s of star t point e r to a tem p point e r .


 Display the inform a tio n from the dat a field of eac h node.

The function traver s e () is used for trave r si n g and displaying the


inform a tio n store d in the list from left to right.

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" ) ;
}

Alter n a t i v e l y the r e is anot h e r way to trave r s e and display the


inform a tio n. That is in reve r s e orde r. The function rev_trav e r s e (), is used
for trave r si n g and displayin g the infor m a tio n store d in the list from right
to left.

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:

# includ e < st dio. h >


# includ e < co nio.h >
# includ e < st dlib. h >

stru ct slinklist
{
int data;
stru ct slinklist *next;
};

typed ef struct slinklist node;

node *start = NULL;

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;
}

node* getno d e()


{
node * newno d e ;
newno d e = (node *) malloc(sizeof(no d e));
printf("\n Ente r data: ");
scanf("%d", &new no d e -> data);
newno d e -> next = NULL;
retu r n newno d e ;
}

int count n o d e( n o d e *ptr)


{
int count = 0 ;
while(pt r != NULL)
{
count + + ;
ptr = ptr -> next;

71
}
retu r n (count);
}

void creat elist(in t n)


{
int i;
node *newnod e;
node *temp;
for(i = 0; i < n; i+ + )
{
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
}
else
{
tem p = start;
while(te m p -> next != NULL)
tem p = temp -> next;
tem p -> next = newno d e ;
}
}
}

void trave r s e()


{
node *temp;
tem p = start;
printf("\n The conte n t s of List (Left to Right): \n");
if(star t = = NULL)
{
printf("\n Empty List");
retu r n ;
}
else
while(te m p != NULL)
{
printf("%d- ->", tem p -> data);
tem p = temp -> next;
}
printf(" X ");
}

void rev_tr av e r s e ( n o d e *start)


{
if(star t = = NULL)
{
retu r n ;
}
else
{
rev_tr av e r s e ( s t a r t -> next);
printf("%d -->", start -> data);
}
}

void insert_at_b e g()


{
node *newnod e;
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
}
else
{
newno d e -> next = start;

72
star t = newno d e;
}
}

void insert_at_e n d()


{
node *newnod e, *temp;
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
}
else
{
tem p = start;
while(te m p -> next != NULL)
tem p = temp -> next;
tem p -> next = 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);
}
}

void delet e_a t_b e g()


{
node *temp;
if(star t = = NULL)
{
printf("\n No nodes are exist..");
retu r n ;
}
else
{
tem p = start;
star t = temp -> next;
free(t e m p );
printf("\n Node delet e d ");
}
}

void delet e_a t_las t()


{
node *temp, *prev;
if(star t = = NULL)
{

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 ");
}
}

void delet e_a t_mid()


{
int ctr = 1, pos, nodec t r;
node *temp, *prev;
if(star t = = NULL)
{
printf("\n Empty List..");
retu r n ;
}
else
{
printf("\n Ente r position of node to delet e: ");
scanf("%d", &pos);
nodect r = count n o d e ( s t a r t );
if(pos > nodec t r)
{
printf("\nThis node does no t exist");

}
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();
}
}

6. 4. Dou b l e Link e d List:

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.

The basic oper a tio n s in a doubl e linked list are:

 Crea tio n.
 Inse r tio n.
 Deletion.
 Traver si n g.

A double linked list is show n in figur e 6.3.1.

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.

The following code gives the struc t u r e definition:

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

Creat i n g a nod e for Dou b l e Link e d List:

Crea ti n g a double linked list star t s with cre a ti n g a node. Sufficien t


me mo ry has to be allocat e d for cre a ti n g a node. The inform a tio n is
stor e d in the mem o ry, allocat e d by using the malloc() function. The
function getno d e(), is used for crea ti n g a node, afte r allocatin g me mo ry
for the stru c t u r e of type node, the inform a ti o n for the item (i.e., data) has
to be rea d from the use r and set left field to NULL and right field also set
to NULL (see figure 6.2.2).

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

Creat i n g a Dou b l e Link e d List with ‘n’ nu m b e r of nod e s :

The following steps are to be followed to create ‘n’ number of nodes:

 Get the new node using get no d e ().

new no d e = g e t n o d e ();

 If the list is empty then start = newnode.

 If the list is not empty, follow the steps given below:

 The left field of the new node is mad e to point the


previou s node.

 The previous node s right field mus t be assig n e d with


add r e s s of the new node.

 Repe a t the above steps ‘n’ times.

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

X 10 200 100 20 300 200 30 X


100 200 300

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 :

The following steps are to be followe d to inser t a new node at the


beginni n g of the list:

 Get the new node using get no d e ().

new no d e = g e t n o d e ( );

 If the list is empty then start = newnode.

 If the list is not empty, follow the steps given below:

new no d e -> right = start;


star t -> left = newno d e ;
star t = new no 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

400 10 200 100 20 300 200 30 X


100 200 300

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:

 Get the new node using getnode()

78
newnode=getnode();

 If the list is empty then start = newnode.

 If the list is not empty follow the steps given below:

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

X 10 200 100 20 300 200 30 400

100 200 300

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

Ins e r t i n g a nod e at an int er m e d i a t e pos i ti o n :


The following steps are followed, to insert a new node in an intermediate position in the list:

 Get the new node using get no d e ().

new no d e = g e t n o d e ( );

 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.

 Store the star ti n g add r e s s (which is in star t point e r) in tem p and


prev pointe r s . Then trave r s e the temp point e r upto the specified
position followed by prev point e r .

 After reac hi n g the specified position, follow the step s given


below:

new no d e -> left = temp;


new no d e -> right = tem p -> right;
tem p -> right -> left = new no d e;
tem p -> right = new no 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:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

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

X 10 200 X 20 300 200 30 X


100 200 300

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

 If the list is not empty, follow the step s given below:

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

X 10 200 100 20 X 200 30 X


100 200 300

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

Del e t i n g a nod e at Int er m e d i a t e pos i t i o n :

The following steps are followe d, to delet e a node from an inter m e d i a t e


position in the list (List must cont ai n more tha n two nodes).

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

 Get the position of the node to delet e.

 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.

 Then perfor m the following steps:

if(pos > 1 && pos < node c t r)


{
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 );
printf("\n node delet e 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

X 10 300 100 20 300 100 30 X


100 200 300

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

Traver s a l and dis pl a yi n g a list (Left to Rig h t ):

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:

 If list is empty then display ‘Empty List’ mess a g e .


 If the list is not empty, follow the step s given below:

tem p = start;
while(te m p != NULL)
{
print tem p -> data;
tem p = tem p -> right;
}

Traver s a l and dis pl a yi n g a list (Ri g h t to Left):

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:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

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:

#i n cl u d e <s t dio. h >


#i n cl u d e <s t dlib. h >
#i n cl u d e <co nio. h >

stru ct dlinklist
{
stru ct dlinklist *left;
int data;
stru ct dlinklist *right;
};

typed ef struct dlinklist node;


node *start = NULL;

node* getno d e()


{
node * newno d e ;
newno d e = (node *) malloc(sizeof(no d e));
printf("\n Ente r data: ");
scanf("%d", &new no d e -> data);
newno d e -> left = NULL;
newno d e -> right = NULL;
retu r n newno d e ;
}

int count n o d e( n o d e *start)


{
if(star t = = NULL)

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;
}

void creat elist(in t n)


{
int i;
node *newnod e;
node *temp;
for(i = 0; i < n; i+ + )
{
newno d e = getno d e();
if(star t = = NULL)
star t = newno d e;
else
{
tem p = start;
while(te m p -> right)
tem p = temp -> right;
tem p -> right = newno d e ;
newno d e -> left = tem p;
}
}
}

void trave r s e_left_to_righ t()


{
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 != NULL)
{
printf("\t %d ", temp -> data);
tem p = temp -> right;
}
}

void trave r s e_rig h t_to_left()


{

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;
}
}

void dll_inser t_b e g ()


{
node *newnod e;
newno d e = getno d e();
if(star t = = NULL)
star t = newno d e;
else
{
newno d e -> right = star t;
star t -> left = newno d e ;
star t = newno d e;
}
}

void dll_inser t_e n d ()


{
node *newnod e, *temp;
newno d e = getno d e();
if(star t = = NULL)
star t = newno d e;
else
{
tem p = start;
while(te m p -> right != NULL)
tem p = temp -> right;
tem p -> right = newno d e ;
newno d e -> left = tem p;
}
}

void dll_inser t_mid()


{
node *newnod e,*te m p ;
int pos, node ct 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 - nodec t r > = 2)
{
printf("\n Position is out of ran g e..");
retu r n ;
}
if(pos > 1 && pos < nodect r)
{
tem p = start;
while(ctr < pos - 1)
{
tem p = temp -> right;
ctr + + ;
}
newno d e -> left = tem p;
newno d e -> right = tem p -> right;
tem p -> right -> left = newno d e;

85
tem p -> right = newno d e ;
}
else
printf("position %d of list is not a middle position ", pos);
}

void dll_delet e_b e g()


{
node *temp;
if(star t = = NULL)
{
printf("\n Empty list");
getch();
retu r n ;
}
else
{
tem p = start;
star t = start -> right;
star t -> left = NULL;
free(t e m p );
}
}

void dll_delet e_last()


{
node *temp;
if(star t = = NULL)
{
printf("\n Empty list");
getch();
retu r n ;
}
else
{
tem p = start;
while(te m p -> right != NULL)
tem p = temp -> right;
tem p -> left -> right = NULL;
free(t e m p );
tem p = NULL;
}
}

void dll_delet e_mid()


{
int i = 0, pos, nodec t r ;
node *temp;
if(star t = = NULL)
{
printf("\n Empty List");
getch();
retu r n ;
}
else
{
printf("\n Ente r the position of the node to delet e: ");
scanf("%d", &pos);
nodect r = count n o d e ( s t a r t );
if(pos > nodec t r)
{
printf("\nt his node does not exist");
getch();
retu r n ;
}
if(pos > 1 && pos < nodect r)
{
tem p = start;
i = 1;

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 .

A circula r single linked list is show n in figur e 6.6.1.

st a rt
100

10 200 20 300 30 400 40 100

100 200 300 400

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

The basic oper a tio n s in a circula r single linked list are:

 Crea tio n.
 Inse r tio n.
 Deletion.
 Traver si n g.

Creat i n g a circ u l a r sin g l e Link e d List with ‘n’ nu m b e r of nod e s :

The following steps are to be followed to create ‘n’ number of nodes:

 Get the new node using get no d e ().

new no d e = getno d e();

 If the list is empty, assign new node as start.

start = newnode;

 If the list is not empty, follow the steps given below:

tem p = start;
while(te m p -> next != NULL)
tem p = tem p -> next;
tem p -> next = newno d e ;

 Repe a t the above steps ‘n’ times.

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 :

The following steps are to be followe d to inser t a new node at the


beginni n g of the circula r list:

 Get the new node using get no d e ().

new no d e = getno d e();

 If the list is empty, assign new node as start.

star t = new no d e ;
new no d e -> next = star t;

 If the list is not empty, follow the steps given below:

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

10 200 20 300 30 400 40 500


100 200 300 400

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:

 Get the new node using getnode().

new no d e = getno d e();

89
 If the list is empty, assign new node as start.

star t = new no d e ;
new no d e -> next = star t;

 If the list is not empty follow the steps given below:


tem p = start;
while(te m p -> next != star t)
tem p = tem p -> next;
tem p -> next = newno 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

10 200 20 300 30 400 40 500


100 200 300 400

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:

 If the list is empty, display a mes s a g e ‘Empty List’.

 If the list is not empty, follow the step s given below:

last = temp = start;


while(las t -> next != sta rt)
last = last -> next;
star t = star t -> next;
last -> next = start;

 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

10 200 20 300 30 400 40 200


100 200 300 400
t e mp

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:

 If the list is empty, display a mes s a g e ‘Empty List’.

 If the list is not empty, follow the step s given below:

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

10 200 20 300 30 100 40 100


100 200 300 400

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 .

Traver s i n g a circ u l a r sin g l e link e d list fro m left to righ t:

The following steps are followe d, to trave r s e a list from left to right:

 If list is empty then display ‘Empty List’ mess a g e .

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);

6.7. A Complete Source Code for the Implementation of Circular Single


Linked List:

# includ e < st dio. h >


# includ e < co nio.h >
# includ e < st dlib. h >

stru ct cslinklist
{
int data;
stru ct cslinklist *next;
};

typed ef struct cslinklist node;


node *start = NULL;
int node ct r ;

node* getno d e()


{
node * newno d e ;
newno d e = (node *) malloc(sizeof(no d e));
printf("\n Ente r data: ");
scanf("%d", &new no d e -> data);
newno d e -> next = NULL;
retu r n newno d e ;
}

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 creat elist(in t n)


{
int i;
node *newnod e;
node *temp;
nodect r = n;
for(i = 0; i < n ; i+ + )
{
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
}
else
{
tem p = start;
while(te m p -> next != NULL)
tem p = temp -> next;
tem p -> next = newno d e ;
}
}
newno d e -> n ex t = star t; /* last node is pointing to startin g node */
}

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 ");
}

void cll_inse rt_b e g()


{
node *newnod e, *last;
newno d e = getno d e();
if(star t = = NULL)
{
star t = newno d e;
newno d e -> next = start;
}
else
{
last = star t;
while(las t -> next != star t)
last = last -> next;
newno d e -> next = start;
star t = newno d e;
last -> next = star t;
}
printf("\n Node insert e d at begin nin g..");
nodect r + + ;
}

void cll_inse rt_e n d()


{
node *newnod e, *temp;
newno d e = getno d e();
if(star t = = NULL )

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 + + ;
}

void cll_inse rt_ mid()


{
node *newnod e, *temp, *prev;
int i, pos ;
newno d e = getno d e();
printf("\n Ente r the position: ");
scanf("%d", &pos);
if(pos > 1 && pos < nodect r)
{
tem p = start;
prev = tem p;
i = 1;
while(i < pos)
{
prev = tem p;
tem p = temp -> next;
i+ + ;
}
prev -> next = newno d e ;
newno d e -> next = tem p;
nodect r + + ;
printf("\n Node insert e d at middle..");
}
else
{
printf("position %d of list is not a middle position ", pos);
}
}

void cll_delet e_b e g()


{
node *temp, *last;
if(star t = = NULL)
{
printf("\n No nodes exist..");
getch();
retu r n ;
}
else
{
last = tem p = start;
while(las t -> next != star t)
last = last -> next;
star t = start -> next;
last -> next = star t;
free(t e m p );
nodect r- -;
printf("\n Node delet e d ..");
if(nodec t r = = 0)
star t = NULL;
}
}

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 ..");
}
}

void cll_delet e_mid()


{
int i = 0, pos;
node *temp, *prev;

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();
}
}

Circ u l a r Dou b l e Link e d List:

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

100 200 300

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

The basic oper a tio n s in a circula r doubl e linked list are:

 Crea tio n.
 Inse r tio n.
 Deletion.
 Traver si n g.

Creat i n g a Circ u l a r Dou b l e Link e d List with ‘n’ nu m b e r of nod e s :

The following steps are to be followed to create ‘n’ number of nodes:

 Get the new node using get no d e ().

new no d e = getno d e();

 If the list is empty, then do the following

star t = new no d e ;
new no d e -> left = star t;
new no d e -> ri g h t = start;

 If the list is not empty, follow the steps given below:

new no d e -> left = star t -> left;


new no d e -> right = start;
star t -> left- > ri g h t = new no d e;
star t -> left = newno d e ;

 Repe a t the above steps ‘n’ times.

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 :

The following steps are to be followe d to inser t a new node at the


beginni n g of the list:

 Get the new node using get no d e ().

97
new no d e = g e t n o d e ( );

 If the list is empty, then

star t = new no d e ;
new no d e -> left = star t;
new no d e -> right = start;

 If the list is not empty, follow the steps given below:

new no d e -> left = star t -> left;


new no d e -> right = start;
star t -> left -> right = new no d e;
star t -> left = newno d e ;
star t = new no d e ;

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

400 10 200 100 20 300 200 30 400

100 200 300

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:

 Get the new node using getnode()

newnode=getnode();

 If the list is empty, then

star t = new no d e ;
new no d e -> left = star t;
new no d e -> right = start;

 If the list is not empty follow the steps given below:

new no d e -> left = star t -> left;


new no d e -> right = start;
star t -> left -> right = new no d e;
star t -> left = newno d e ;

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

400 10 200 100 20 300 200 30 400

100 200 300

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

Ins e r t i n g a nod e at an int er m e d i a t e pos i ti o n :


The following steps are followed, to insert a new node in an intermediate position in the list:

 Get the new node using get no d e ().

new no d e = g e t n o d e ( );

 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.

 Store the star ti n g add r e s s (which is in star t point e r) in tem p and


prev pointe r s . Then trave r s e the temp point e r upto the specified
position followed by prev point e r .

 After reac hi n g the specified position, follow the step s given


below:

new no d e -> left = temp;


new no d e -> right = tem p -> right;
tem p -> right -> left = new no d e;
tem p -> right = new no d e ;
nodec t r + + ;

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:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

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

300 10 200 300 20 300 200 30 200

100 200 300

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:

 If list is empty then display ‘Empty List’ mess a g e

 If the list is not empty, follow the step s given below:

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

200 10 200 100 20 100 200 30 100

100 200 300

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

Del e t i n g a nod e at Int er m e d i a t e pos i t i o n :

The following steps are followe d, to delet e a node from an inter m e d i a t e


position in the list (List must cont ai n more tha n two node).

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

 Get the position of the node to delet e.

 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.

 Then perfor m the following steps:

if(pos > 1 && pos < node c t r)


{

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

300 10 300 100 20 300 100 30 100

100 200 300

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

Traver s i n g a circ u l a r dou b l e link e d list fro m left to rig h t:

The following steps are followe d, to trave r s e a list from left to right:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:

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 function cdll_display_left _right(), is used for trave r si n g from left to


right.

Traver s i n g a circ u l a r dou b l e link e d list fro m rig h t to left:

The following steps are followe d, to trave r s e a list from right to left:

 If list is empty then display ‘Empty List’ mess a g e .

 If the list is not empty, follow the step s given below:


tem p = start;
do
{

102
tem p = tem p -> left;
print tem p -> data;
} while(t e m p != sta rt);

The function cdll_display_righ t_left(), is used for trave r si n g from right to


left.

6.9. A Complete Source Code for the Implementation of Circular Double


Linked List:

# includ e < st dio. h >


# includ e < st dlib. h >
# includ e < co nio.h >

stru ct cdlinklist
{
stru ct cdlinklist *left;
int data;
stru ct cdlinklist *right;

};

typed ef struct cdlinklist node;


node *start = NULL;
int node ct r ;

node* getno d e()


{
node * newno d e ;
newno d e = (node *) malloc(sizeof(no d e));
printf("\n Ente r data: ");
scanf("%d", &new no d e -> data);
newno d e -> left = NULL;
newno d e -> right = NULL;
retu r n newno d e ;
}

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;
}

void cdll_cre a t elist(int n)


{
int i;
node *newnod e, *temp;
if(star t = = NULL)

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..");
}
}

void cdll_display_left_righ t()


{
node *temp;
tem p = start;
if(star t = = NULL)
printf("\n Empty List");
else
{
printf("\n The conte n t s of List: ");
printf(" %d ", tem p -> data);
tem p = temp -> right;
while(te m p != start)
{
printf(" %d ", tem p -> data);
tem p = temp -> right;
}
}
}

void cdll_display_rig h t_left()


{
node *temp;
tem p = start;
if(star t = = NULL)
printf("\n Empty List");
else
{
printf("\n The conte n t s of List: ");
do
{
tem p = temp -> left;
printf("\t%d", temp -> data);
}while(te m p != start);
}
}

void cdll_inse r t_b e g()


{
node *newnod e;
newno d e = getno d e();
nodect r + + ;
if(star t = = NULL)
{

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;
}
}

void cdll_inse r t_en d ()


{
node *newnod e,*te m p ;
newno d e = getno d e();
nodect r + + ;
if(star t = = NULL)
{
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 ;
}
printf("\n Node Inser t e d at End");
}

void cdll_inse r t_mi d()


{
node *newnod e, *temp, *prev;
int pos, ctr = 1;
newno d e = getno d e();
printf("\n Ente r the position: ");
scanf("%d", &pos);
if(pos - nodec t r > = 2)
{
printf("\n Position is out of ran g e..");
retu r n ;
}
if(pos > 1 && pos < = nodec t r)
{
tem p = start;
while(ctr < pos - 1)
{
tem p = temp -> right;
ctr + + ;
}
newno d e -> left = tem p;
newno d e -> right = tem p -> right;
tem p -> right -> left = newno d e;
tem p -> right = newno d e ;
nodect r + + ;
printf("\n Node Inser t e d at Middle.. ");
}
else
{
printf("position %d of list is not a middle position", pos);

}
}

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..");
}
}

void cdll_delet e_last()


{
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;
while(te m p -> right != star t)
tem p = temp -> right;
tem p -> left -> right = temp -> right;
tem p -> right -> left = temp -> left;
free(t e m p );
}
printf("\n Node delet e d from end ");
}
}

void cdll_delet e_mi d()


{
int ctr = 1, pos;
node *temp;
if( start = = NULL)
{
printf("\n No nodes exist..");
getch();
retu r n ;
}

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();
}
}

6. 9. Link e d List Impl e m e n t a t i o n of Sta c k:

We can repr e s e n t a stack as a linke d list. In a stack push and pop


oper a tio n s are perfor m e d at one end called top. We can perfor m similar
oper a tio n s at one end of list using top point e r. The linke d stack looks as
show n in figure 6.9.1:

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

The pro g r a m for link e d list imp l e m e n t a t i o n of sta c k:

# includ e < st dio. h >


# includ e < co nio.h >
# includ e < st dlib. h >

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;

node* getno d e()


{
stru ct stack *temp;
tem p = ( n o d e *) malloc( sizeof(nod e)) ;
printf("\n Ente r data ");

108
scanf("%d", &tem p -> dat a);
tem p -> next = NULL;
retu r n tem p;
}

void push(no d e *newno d e)


{
node *temp;
if( newno d e = = NULL )
{
printf("\n Stack Overflow..");
retu r n ;
}
if(star t = = NULL)
{
star t = newno d e;
top = newno d e;
}
else
{
tem p = start;
while( tem p -> next != NULL)
tem p = temp -> next;
tem p -> next = newno d e ;
top = newno d e;
}
printf("\n\n\t Data push e d into stack");
}

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' );
}

6. 1 0 . Link e d List Impl e m e n t a t i o n of Que u e :

We can repr e s e n t a que u e as a linke d list. In a que u e dat a is delet e d


from the front end and inser t e d at the rear end. We can perfor m similar
oper a tio n s on the two ends of a list. We use two point e r s front and rear
for our linked que u e imple m e n t a t i o n .

The linke d que u e looks as show n in figur e 6.10.1:

110
fr o nt rear
100 400

10 200 20 300 30 400 40 X


100 200 300 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

The pro g r a m for link e d list imp l e m e n t a t i o n of qu e u e :

# includ e < st dio. h >


# includ e < st dlib. h >
# includ e < co nio.h >

stru ct que u e
{
int data;
stru ct que u e *next;
};

typed ef struct queu e node;


node *front = NULL;
node *rear = NULL;

node* getno d e()


{
node *temp;
tem p = (node *) malloc(sizeof(no d e)) ;
printf("\n Ente r data ");
scanf("%d", &tem p -> dat a);
tem p -> next = NULL;
retu r n tem p;
}

void insert Q()


{
node *newnod e;
newno d e = getno d e();
if(new no d e = = NULL)
{
printf("\n Queu e Full");
retu r n ;
}
if(front = = NULL)
{
front = newno d e ;
rea r = newno d e;
}
else
{
rea r -> next = newno d e;
rea r = newno d e;
}
printf("\n\n\t Data Insert e d into the Queu e..");
}

void delet eQ()


{
node *temp;
if(front = = NULL)
{
printf("\n\n\t Empty Queu e..");
retu r n ;

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

A dat a struc t u r e is said to be linear if its elem e n t s form a sequ e n c e or a


linea r list. Previous linea r data struc t u r e s that we have studie d like
arr ay s, stacks, queu e s and linked lists orga niz e dat a in linea r orde r.

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.

7.2. BINARY TREE:

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

The children of the same parent are called 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

If the r e is a pat h from node A to node B, then A is called an


ance s t o r of B and
B is called a descendent of A.

Subtree

Any node of a tre e, with all of its desc e n d a n t s is a subt r e e .

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.

The maximum number of nodes at any level is 2n.

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.

Assigning level numbers and Numbering of nodes for a binary tree:

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

Figure 7.2.2. Lev el by level number ing of binary tree

Properties of binary trees:

Some of the important properties of a binary tree are as follows:

1. If h = height of a binary tree, then


a.
Maximum number of leaves = 2h
b.
Maximum number of nodes = 2h + 1 - 1

2. If a binary tree contains m nodes at level l, it contains at most 2m nodes at level l + 1.

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.

4. The total number of edges in a full binary tree with n node is n - 1.

Strictly Binary tree:

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.

Full Binary tree:

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.

A full binary tree of height h contains 2h leaves and, 2h - 1 non-leaf nodes.


h
l h 1
Thus by induction, total number of nodes ( tn )   2  2 1.
l 0
3+1
For example, a full binary tree of height 3 contains 2 – 1 = 15 nodes.

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

Complete Binary tree:

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

Binary Search Tree:

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

Bin a ry S e arc h T r e e No t a Bin a ry S e arc h T r e e


(a) ( b)

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

Data Structures for Binary Trees:

1. Arrays; especially suited for complete and full binary trees.


2. Pointer-based.

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

Link e d Repr e s e n t a t i o n (Poi n t e r bas e d ) :

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.

The adva n t a g e of using linke d rep r e s e n t a t i o n of binary tree is that:

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 .

The disadva n t a g e s of linke d repr e s e n t a t i o n of bina ry tre e includ e s :

 Given a node struc t u r e , it is difficult to dete r m i n e its pare n t


node.

 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 .

The stru c t u r e definition, node repr e s e n t a t i o n empty bina ry tree is show n


in figure 7.2.6 and the linked rep r e s e n t a t i o n of bina ry tree using this
node struc t u r e is given in figure 7.2.7.

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

7.3. BINARY TREE TRAVERSAL TECHNIQUES:

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

In the first thre e trave r s a l met ho d s , the left subt r e e of a node is


trave r s e d befor e the right subt r e e . The differe n c e amon g the m come s
from the differe n c e in the time at which a root node is visite d.

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:

1. Visit the left subt r e e , using inord e r.


2. Visit the root.
3. Visit the right subt r e e , using inord e r .

The algorit h m for inord e r trave r s a l is as follows:

void inord e r ( n o d e *root)


{
if(root != NULL)
{
inord e r ( r o o t- >lchild);
print root -> dat a;
inord e r ( r o o t- > rc hild);
}
}

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:

1. Visit the root.


2. Visit the left subt r e e , using preo r d e r .
3. Visit the right subt r e e , using preor d e r .

The algorit h m for preor d e r trave r s a l is as follows:

void preor d e r ( n o d e *root)


{
if( root != NULL )
{

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:

1. Visit the left subt r e e , using postor d e r .


2. Visit the right subt r e e , using postor d e r
3. Visit the root.

The algorit h m for posto r d e r trave r s a l is as follows:

void postor d e r ( n o d e *root)


{
if( root != NULL )
{
posto r d e r (root -> lchild);
posto r d e r (root -> rchild);
print (root -> dat a);
}
}

Level ord e r Traver s a l:

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.

The algorit h m for level orde r trave r s a l is as follows:

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

For m a t i o n of Bin ary Tre e fro m its Traver s a l:

Som e ti m e s it is req ui r e d to const r u c t a bina ry tre e if its trave r s a l s are


know n. From a single trave r s al it is not possible to cons t r u c t uniqu e
bina ry tree. Howev e r if two are trave r s al s then corr e s p o n di n g tre e can
be dra w n uniqu ely. The basic principle for form ul a tio n is as follows:
If the preor d e r trave r s al is given, then the first node is the root node. If
the postor d e r trave r s a l is given then the last node is the root node. Once
the root node is identifie d, all the node s in the left sub- tre e s and right
sub- tree s of the root node can be identified.

Sam e tech ni q u e can be applie d repe a t e d ly to form sub- tree s .

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:

Const r u c t a bina ry tree from a given preo r d e r and inord e r sequ e n c e :

Preorder: A B D G C E H I F
Inorder: D G B A H E I C F

Solution:

From Preord er sequ e n c e A B D G C E H I F, the root is: A

From Inord e r sequ e n c e D G B A H E I C F, we get the left and right sub


tre e s:

Left sub tree is: D G B

Right sub tree is: H E I C F

The Binary tree upto this point looks like:

123
A

D G B H E I C F

To find the root, left and right sub tree s for D G B:

From the preorder sequence B D G, the root of tree is: B

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.

The Binary tree upto this point looks like:


A

B H E I C F

D G

To find the root, left and right sub tree s for D G:

From the preorder sequence D G, the root of the tree is: D

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

To find the root, left and right sub tree s for H E I C F:

From the preorder sequence C E H I F, the root of the left sub tree is: C

From the inord e r sequ e n c e H E I C F, we can find that H E I are at the


left of C and F is at the right of C.

The Binary tree upto this point looks like:

124
A

B C

D H E I F

To find the root, left and right sub tree s for H E I:

From the preorder sequence E H I, the root of the tree is: E

From the inord e r sequ e n c e H E I, we can find that H is at the left of E


and I is at the right of E.

The Binary tree upto this point looks like:

125
A

B C

D E F

G H I

Example 2:

Const r u c t a bina ry tree from a given postor d e r and inord e r sequ e n c e :

Inorder: n1 n2 n3 n4 n5 n6 n7 n8 n9
Postorder: n1 n3 n5 n4 n2 n8 n7 n9 n6

Solution:

From Postor d e r sequ e n c e n1 n3 n5 n4 n2 n8 n7 n9 n6 , the root is: n6

From Inord e r sequ e n c e n1 n2 n3 n4 n5 n6 n7 n8 n9 , we get the left and


right sub tree s:

Left sub tree is: n1 n2 n3 n4 n5


Right sub tree is: n7 n8 n9

The Binary tree upto this point looks like:

n6

n1 n2 n3 n4 n5 n7 n8 n9

To find the root, left and right sub tree s for n1 n2 n3 n4 n5 :

From the postorder sequence n1 n3 n5 n4 n2, the root of tree is: n2

From the inord e r sequ e n c e n1 n2 n3 n4 n5 , we can find that n1 is to the


left of n2 and n3 n4 n5 are to the right of n2.

The Binary tree upto this point looks like:

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

From the inord e r sequ e n c e n3 n4 n5 , we can find that n3 is to the left of


n4 and n5 is to the right of n4.

The Binary tree upto this point looks like:


n6

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

From the inord e r sequ e n c e n7 n8 n9 , we can find that n7 and n8 are to


the left of n9 and no right subt r e e for n9.

The Binary tree upto this point looks like:


n6

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

From the inord e r sequ e n c e n7 n8 , we can find that ther e is no left


subt r e e for n7 and n8 is to the right of n7.

138
The Binary tree upto this point looks like:

n6

n2 n9

n1 n4 n7

n3 n5 n8

Binary Tree Creation and Traversal Using Arrays:

This progr a m perfor m s the following oper a tio n s:

1. Crea t e s a comple t e Binary Tree


2. Inord e r trave r s al
3. Preor d e r trave r s al
4. Postor d e r trave r s al
5. Level orde r trave r s al
6. Prints leaf nodes
7. Finds height of the tree creat e d

# includ e < st dio. h >


# includ e < st dlib. h >

struct tree
{
stru ct tree* lchild;
char data[1 0];
stru ct tree* rchild;
};

typed ef struct tree node;


int ctr;
node *tree[1 0 0];

node* getno d e()


{
node *temp ;
tem p = (node*) malloc(sizeof(nod e));
printf("\n Ente r Data: ");
scanf("%s",te m p- > d a t a);
tem p- >lchild = NULL;
tem p- > rc hild = NULL;
retu r n tem p;
}

void creat e_fbin a ry t r e e ()


{
int j, i=0;
printf("\n How many nodes you want: ");
scanf("%d",&ct r);
tree[0] = getno d e();
j = ctr;
j--;
do
{
if( j > 0 ) /* left child */

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);
}

void inord e r( n o d e *root)


{
if( root != NULL )
{
inord e r( r o o t- >lchild);
printf("%3s",roo t- > d a t a );
inord e r( r o o t- > rc hild);
}
}

void preo r d e r ( n o d e *root)


{
if( root != NULL )
{
printf("%3s",roo t- > d a t a );
preo r d e r ( r o o t- >lchild);
preo r d e r ( r o o t- > rc hild);
}
}

void postor d e r ( n o d e *root)


{
if( root != NULL )
{
postor d e r ( r o o t- >lchild);
postor d e r ( r o o t- > rc hild);
printf("%3s",roo t- > d a t a );
}
}
void levelor d e r ()
{
int j;
for(j = 0; j < ctr; j+ + )
{
if(tree[j] != NULL)
printf("%3s",tr e e [j]- > d a t a );
}
}

void print_leaf(no d e *root)


{
if(root != NULL)
{
if(root- >lchild = = NULL && root- > rc hild = = NULL)
printf("%3s ",root- > d a t a);
print_leaf(root- >lchild);
print_leaf(root- > r c hild);
}
}

int height(n o d e *root)


{
if(root = = NULL)
{

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]));
}

Binary Tree Creation and Traversal Using Pointers:

This progr a m perfor m s the following oper a tio n s:

1. Crea t e s a comple t e Binary Tree


2. Inord e r trave r s al
3. Preor d e r trave r s al
4. Postor d e r trave r s al
5. Level orde r trave r s al
6. Prints leaf nodes
7. Finds height of the tree creat e d
8. Delete s last node
9. Finds height of the tree creat e d

# includ e < st dio. h >


# includ e < st dlib. h >

stru ct tree
{
stru ct tree* lchild;
char data[1 0];
stru ct tree* rchild;
};

typed ef struct tree node;


node *Q[50];
int node_ct r;

node* getno d e(void)


{
node *temp ;
tem p = (node*) malloc(sizeof(nod e));
printf("\n Ente r Data: ");
fflush(st din);
scanf("%s",te m p- > d a t a);
tem p- >lchild = NULL;
tem p- > rc hild = NULL;
retu r n tem p;
}

void creat e_bin a ry t r e e ( n o d e *root)


{
char option;

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);
}

printf("\n Node %s has Right SubTre e(Y/N) ",root- >d a t a);


fflush(st din);
scanf("%c",&op tion);
if( option = = 'Y' || option = = 'y')
{
root- > rc hild = getno d e ();
creat e_bin a r y t r e e ( r o o t- > rc hild);
}
else
{
root- > rc hild = NULL;
creat e_bin a r y t r e e ( r o o t- > rc hild);
}
}
}

void make_Qu e u e ( n o d e *root,int par e n t)


{
if(root != NULL)
{
node_ct r + + ;
Q[par e n t] = root;
make_Qu e u e ( r o o t- >lchild,p a r e n t*2 + 1 );
make_Qu e u e ( r o o t- > rc hild,p a r e n t*2 + 2 );
}
}

delet e_no d e ( n o d e *root, int par e n t)


{
int index = 0;
if(root = = NULL)
printf("\n Empty TREE ");
else
{
node_ct r = 0;
make_Qu e u e ( r o o t, 0);
index = node_ct r- 1;
Q[index] = NULL;
pare n t = (index- 1) /2;
if( 2* pare n t + 1 = = index )
Q[par e n t]- >lchild = NULL;
else
Q[par e n t]- > rc hild = NULL;
}
printf("\n Node Delete d ..");
}

void inord e r( n o d e *root)


{
if(root != NULL)
{
inord e r( r o o t- >lchild);
printf("%3s",roo t- > d a t a );

142
inord e r( r o o t- > rc hild);
}
}

void preo r d e r ( n o d e *root)


{
if( root != NULL )
{
printf("%3s",roo t- > d a t a );
preo r d e r ( r o o t- >lchild);
preo r d e r ( r o o t- > rc hild);
}
}

void postor d e r ( n o d e *root)


{
if( root != NULL )
{
postor d e r ( r o o t- >lchild);
postor d e r ( r o o t- > rc hild);
printf("%3s", root- > d a t a);
}
}

void print_leaf(no d e *root)


{
if(root != NULL)
{
if(root- >lchild = = NULL && root- > rc hild = = NULL)
printf("%3s ",root- > d a t a);
print_leaf(root- >lchild);
print_leaf(root- > r c hild);
}
}
int height(n o d e *root)
{
if(root = = NULL)
retu r n -1;
else
retu r n (1 + max(heig h t( r oo t- >lchild), height(r oo t- > rc hild)));
}

void print_tr e e( n o d e *root, int line)


{
int i;
if(root != NULL)
{
print_tr e e( r oo t- > rc hild,lin e + 1 ) ;
printf("\n");
for(i = 0;i < li n e;i + + )
printf(" ");
printf("%s", root- > d a t a );
print_tr e e( r oo t- >lchild,line + 1 ) ;
}
}

void level_ord e r( n o d e *Q[],int ctr)


{
int i;
for( i = 0; i < ctr ; i+ + )
{
if( Q[i] != NULL )
printf("%5s",Q[i]- > d a t a );
}
}

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);
}

Non Recursive Binary Tree Traversal Algorithms:

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)
}

pop the elem e n t from the stack and make it as vert ex

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.

Once an expression tree is constructed we can traverse it in three ways:

 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.

An algorithm to convert a postfix expression into an expression tree is as follows:

1. Read the expression one symbol at a time.

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:

Construct an expression tree for the postfix expression: a b + c d e + * *

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

Now a ‘+’ is read, so two trees are merged.

+
+ 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

For the above tree:


Inord e r form of the expre s sio n: a + b * c * d + e
Preo r d e r form of the expr e s sio n: * + a b * c + d e
Postor d e r form of the expr e s si o n: a b + c d e + * *

Example 2:

Construct an expression tree for the arithmetic expression:

(A + B * C) – ((D * E + F) / G)

Solution:

First convert the infix expression into postfix notation.

Postfix notation of the arithmetic expression is: A B C * + D E * F + G / -

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.

If all the edge s in a gra p h are undir e c t e d , then the gra p h is an


undir e c t e d gra p h. The grap h of figur e s 7.5.1(a) is undir e c t e d gra p h s . If
all the edg e s are direc t e d ; then the grap h is a direc t e d gra p h. The gra p h
of figur e 7.5.1(b) is a direct e d gra p h. A direc t e d grap h is also called as
digra p h .

A gra p h G is conn e c t e d if and only if ther e is a simple path betw e e n any


two nodes in G.

A grap h G is said to be compl et e if every node a in G is adjac e n t to every


othe r node v in G. A comple t e gra p h with n nodes will have n(n- 1)/2
edge s. For exam pl e, Figur e 7.5.1.(a) and figure 7.5.1.(d) are compl e t e
gra p h s .

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 graph G’ = (V’, E’) is a sub-graph of graph G = (V, E) iff V’  V and E’  E.

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.

Let T be a spanning tree of a graph G. Then

1. Any two vertices in T are connected by a unique simple path.


2. If any edge is removed from T, then T becomes disconnected.
3. If we add any edge into T, then the new graph will contain a cycle.
4. Number of edges in T is n-1.

Representation of Graphs:

There are two ways of representing digraphs. They are:

 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 if there is an edge from v i to v j


a  
i, j
 0 otherwise
The matrix is symmetric in case of undirected graph, while it may be asymmetric if the graph is
directed. This matrix is also called as Boolean matrix or bit matrix.

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 :

In this repr e s e n t a t i o n , the n rows of the adjace n cy mat rix are


repr e s e n t e d as n linke d lists. An array Adj[1, 2, . . . . . n] of point e r s
wher e for 1 < v < n, Adj[v] points to a linked list contai ni n g the vertice s
which are adjac e n t to v (i.e. the vertice s that can be reac h e d from v by a
single edge). If the edg e s have weight s the n thes e weigh t s may also be
stor e d in the linked list elem e n t s . For the gra p h G in figure 7.5.2 (a), the
adjac e n c y list in show n in figur e 7.5.4 (b).

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

 1 if there is an edge j incident to v i


a i, j  
 0 otherwise

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).

7.6. Minimum Spanning Tree (MST):

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:

Let's consider a couple of real-world examples on minimum spanning tree:

 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.

7.6.1. Kruskal’s Algorithm

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.

Kruskal’s Algorithm for minimal spanning tree is as follows:

1. Make the tree T empty.


2. Repe a t the steps 3, 4 and 5 as long as T cont ain s less than n - 1
edge s and E is not empty othe r wi s e, proc e e d to step 6.
3. Choos e an edge (v, w) from E of lowest cost.
4. Delete (v, w) from E.
5. If (v, w) does not crea t e a cycle in T
the n Add (v, w) to T
else disca r d (v, w)
6. If T cont ai n s fewer than n - 1 edg e s then print no span ni n g tree.

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

Arrang e all the edge s in the increasi n g order of their costs:

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)

The stag e s in Kruskal’s algorit h m for minim al span ni n g tree is as follows:

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

(1, 2) 10 The edge betw e e n vertices 1 and 2 is the


1 2
3 first edge select e d . It is includ e d in the
span nin g tree.
4
5
6

(3, 6) 15 Next, the edge betw e e n vertices 3 and 6


1 2
is select e d and include d in the tree.
3

4
5
6

(4, 6) 20 The edge betw e e n vertice s 4 and 6 is


1 2
next include d in the tree.
3

4
5
6

(2, 6) 25 The edge betw e e n vertice s 2 and 6 is


1 2
consid e r e d next and includ e d in the tree.
3

4
5
6

(1, 4) 30 The edge betw e e n the vertice s 1 and 4 is


Reject disca r d e d as its inclusion crea t e s a cycle.

(3, 5) 35 Finally, the edg e betw e e n vertices 3 and


1 2
3
5 is conside r e d and include d in the tree
built. This complet e s the tree.
4 5 The cost of the minimal span ni n g tree is
6 10 5 .

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)

The stag e s in Kruskal’s algorit h m for minim al span ni n g tree is as follows:

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

(1, 6) 10 1 The edge betw e e n vertices 1 and 6 is the


2 first edge select e d . It is includ e d in the
span nin g tree.
6
3
7

5
4

(3, 4) 12 1 Next, the edge betw e e n vertices 3 and 4


2 is select e d and include d in the tree.

6
3
7

5
4

(2, 7) 14 1 The edge betw e e n vertice s 2 and 7 is


2 next include d in the tree.

6
3
7

5
4

(2, 3) 16 1 The edge betw e e n vertice s 2 and 3 is


2 next include d in the tree.

6
3
7

5
4

The edge betw e e n the vertice s 4 and 7 is


(4, 7) 18 Reject disca r d e d as its inclusion crea t e s a cycle.

(4, 5) 22 1 The edge betw e e n vertice s 4 and 7 is


2 consid e r e d next and includ e d in the tree.

6
3
7

5
4

(5, 7) 24 The edge betw e e n the vertice s 5 and 7 is


Reject disca r d e d as its inclusion crea t e s a cycle.

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

7. 6. 2 . Rea c h a b i l i t y Matrix (Wars h all’s Algorith m) :

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.

A 1 entry indica t e s a pair of vertice s, which are conn e c t e d , and O entry


indicat e s a pair, which are not. This mat rix is called a reacha bility matrix
or path matrix for the grap h. It is also called the transitiv e closur e of the
origin al adjac e n c y mat rix.

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

We begin with the adjac e n cy matrix of the gra p h ‘A 0 ’

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).

Before doing so we notice that only 1 entry in A 0 mus t rem ai n 1 in A1 ,


since in Boolea n algeb r a 1 + (any thing) = 1. Since thes e are only nine 0
ent rie s in A0 , ther e are only nine ent rie s in A 0 that nee d to be upda t e d .

A1 [1, 1] = A0 [1, 1] ۷ (A 0 [1, 1] ٨ A0 [1, 1]) = 0 ۷ (0 ٨ 0) = 0


A1 [2, 1] = A0 [2, 1] ۷ (A 0 [2, 1] ٨ A0 [1, 1]) = 0 ۷ (0 ٨ 0) = 0
A1 [2, 2] = A0 [2, 2] ۷ (A 0 [2, 1] ٨ A0 [1, 2]) = 0 ۷ (0 ٨ 1) = 0
A1 [3, 1] = A0 [3, 1] ۷ (A 0 [3, 1] ٨ A0 [1, 1]) = 0 ۷ (0 ٨ 0) = 0
A1 [3, 2] = A0 [3, 2] ۷ (A 0 [3, 1] ٨ A0 [1, 2]) = 0 ۷ (0 ٨ 1) = 0
A1 [3, 3] = A0 [3, 3] ۷ (A 0 [3, 1] ٨ A0 [1, 3]) = 0 ۷ (0 ٨ 1) = 0
A1 [3, 4] = A0 [3, 4] ۷ (A 0 [3, 1] ٨ A0 [1, 4]) = 0 ۷ (0 ٨ 0) = 0
A1 [4, 4] = A0 [4, 4] ۷ (A 0 [4, 1] ٨ A0 [1, 4]) = 0 ۷ (1 ٨ 0) = 0

1 0 1 1 0
 
2 0 0 1 1
A1  0
3 0 0 0
 
4 1 1 1 0 

Next, A2 mus t be calcula t e d from A1 ; but again we nee d to upda t e the 0


ent rie s,

A2 [1, 1] = A1 [1, 1] ۷ (A 1 [1, 2] ٨ A1 [2, 1]) = 0 ۷ (1 ٨ 0) = 0


A2 [1, 4] = A1 [1, 4] ۷ (A 1 [1, 2] ٨ A1 [2, 4]) = 0 ۷ (1 ٨ 1) = 1
A2 [2, 1] = A1 [2, 1] ۷ (A 1 [2, 2] ٨ A1 [2, 1]) = 0 ۷ (0 ٨ 0) = 0
A2 [2, 2] = A1 [2, 2] ۷ (A 1 [2, 2] ٨ A1 [2, 2]) = 0 ۷ (0 ٨ 0) = 0
A2 [3, 1] = A1 [3, 1] ۷ (A 1 [3, 2] ٨ A1 [2, 1]) = 0 ۷ (0 ٨ 0) = 0
A2 [3, 2] = A1 [3, 2] ۷ (A 1 [3, 2] ٨ A1 [2, 2]) = 0 ۷ (0 ٨ 0) = 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 

This matrix has only seven 0 entri e s, and so to comp u t e A 3 , we nee d to do


only seve n comp u t a t i o n s .

A3 [1, 1] = A2 [1, 1] ۷ (A 2 [1, 3] ٨ A2 [3, 1]) = 0 ۷ (1 ٨ 0) = 0


A3 [2, 1] = A2 [2, 1] ۷ (A 2 [2, 3] ٨ A2 [3, 1]) = 0 ۷ (1 ٨ 0) = 0
A3 [2, 2] = A2 [2, 2] ۷ (A 2 [2, 3] ٨ A2 [3, 2]) = 0 ۷ (1 ٨ 0) = 0
A3 [3, 1] = A2 [3, 1] ۷ (A 2 [3, 3] ٨ A2 [3, 1]) = 0 ۷ (0 ٨ 0) = 0
A3 [3, 2] = A2 [3, 2] ۷ (A 2 [3, 3] ٨ A2 [3, 2]) = 0 ۷ (0 ٨ 0) = 0
A3 [3, 3] = A2 [3, 3] ۷ (A 2 [3, 3] ٨ A2 [3, 3]) = 0 ۷ (0 ٨ 0) = 0
A3 [3, 4] = A2 [3, 4] ۷ (A 2 [3, 3] ٨ A2 [3, 4]) = 0 ۷ (0 ٨ 0) = 0

1 0 1 1 1
 
2 0 0 1 1
A3  0
3 0 0 0
 
4 1 1 1 1 

Once A3 is calcula t e d , we use the upda t e rule to calcula t e A 4 and stop.


This matrix is the reac h a bility matrix for the gra p h.

A4 [1, 1] = A3 [1, 1] ۷ (A 3 [1, 4] ٨ A3 [4, 1]) = 0 ۷ (1 ٨ 1) = 0 ۷ 1 = 1


A4 [2, 1] = A3 [2, 1] ۷ (A 3 [2, 4] ٨ A3 [4, 1]) = 0 ۷ (1 ٨ 1) = 0 ۷ 1 = 1
A4 [2, 2] = A3 [2, 2] ۷ (A 3 [2, 4] ٨ A3 [4, 2]) = 0 ۷ (1 ٨ 1) = 0 ۷ 1 = 1
A4 [3, 1] = A3 [3, 1] ۷ (A 3 [3, 4] ٨ A3 [4, 1]) = 0 ۷ (0 ٨ 1) = 0 ۷ 0 = 0
A4 [3, 2] = A3 [3, 2] ۷ (A 3 [3, 4] ٨ A3 [4, 2]) = 0 ۷ (0 ٨ 1) = 0 ۷ 0 = 0
A4 [3, 3] = A3 [3, 3] ۷ (A 3 [3, 4] ٨ A3 [4, 3]) = 0 ۷ (0 ٨ 1) = 0 ۷ 0 = 0
A4 [3, 4] = A3 [3, 4] ۷ (A 3 [3, 4] ٨ A3 [4, 4]) = 0 ۷ (0 ٨ 1) = 0 ۷ 0 = 0

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:

 Breadth first traversal (BFT)


 Depth first traversal (DFT)
The BFT will use a queue as an auxiliary structure to hold nodes for future processing and the DFT
will use a STACK.

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:

1. STATUS = 1 (Ready state): The initial state of the node N.

2. STATUS = 2 (Waiting stat e): The node N is on the QUEUE or


STACK, waiting to be proce s s e d .

3. STATUS = 3 (Proce s s e d stat e): The node N has bee n proce s s e d .

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.

Bre a d t h first se ar c h and trav er s a l :

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.

Breadth first traversal algorithm on graph G is as follows:

This algorithm executes a BFT on graph G beginning at a starting node A.

1. Initialize all node s to the rea dy stat e (STATUS = 1).

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:

a. Remove the front node N of QUEUE. Proce s s N and chan g e


the stat u s of N to the proce s s e d stat e (STATUS = 3).

b. Add to the rea r of QUEUE all the neigh b o r s of N that are in


the rea dy stat e (STATUS = 1), and chan g e their stat u s to the
waiting stat e (STATUS = 2).

4. Exit.

Dep t h firs t se ar c h an d trav er s a l:

Dept h first sea rc h of undir e c t e d gra p h proce e d s as follows: First we


exa mi n e the starti n g node V. Next an unvisite d vert ex 'W' adjac e n t to 'V'
is select e d and a dept h first sear c h from 'W' is initiat e d. When a vert ex
'U' is reac h e d such that all its adjac e n t vertice s have been visite d, we
back up to the last vert ex visited, which has an unvisite d vert ex 'W'
adjac e n t to it and initiat e a dept h first sear c h from W. The sear c h
ter mi n a t e s when no unvisite d vert ex can be rea c h e d from any of the
visited ones.

This algorit h m is similar to the inord e r trave r s a l of bina ry tree. DFT


algorit h m is similar to BFT excep t now use a STACK inste a d of the
QUEUE. Again field STATUS is use d to tell us the curr e n t stat u s of a
node.

The algorit h m for dept h first trave r s a l on a gra p h G is as follows.

This algorithm executes a DFT on graph G beginning at a starting node A.

1. Initialize all node s to the rea dy stat e (STATUS = 1).

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).

3. Repe a t the following steps until STACK is empty:

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).

b. Push all the neigh b o r s of N that are in the rea dy stat e


(STATUS = 1), and chan g e their stat u s to the waiting stat e
(STATUS = 2).
4. Exit.

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

Bre a d t h - first se ar c h and trav er s a l :

The steps involved in breadth first traversal are as follows:

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.

Depth-first search and traversal:

The steps involved in depth first traversal are as follows:

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

Bre a d t h first se ar c h and trav er s a l :

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

7. 7. Gen e r a l Tree s (m- ary tre e ):

If in a tre e, the outd e g r e e of every node is less tha n or equ al to m , the


tre e is called an m- ary tre e. If the outde g r e e of every node is exactly
equal to m or zero the n the tre e is called a full or com pl e t e m- ary tre e.
For m = 2, the tree s are called binary and full binary tree s.

Differences between trees and binary trees:

TREE BINARY TREE


Each element in a tree can have any number of Each element in a binary tree has at most two
subtrees. subtrees.
The subtrees of each element in a binary tree
The subtrees in a tree are unordered. are ordered (i.e. we distinguish between left and
right subtrees).

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 .

 As a first step, we delet e all the bra n c h e s origin a ti n g in every


node exce p t the left most bra nc h.
 We draw edg e s from a node to the node on the right, if any,
which is situa t e d at the sam e level.

 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 :

 The left son is the node, which is imme di a t e ly below the


given node, and the right son is the node to the imme di a t e
right of the given node on the sam e horizon t al line. Such a
bina ry tree will not have a right subt r e e .

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:

Stage 1 tree using the above mentioned procedure is as follows:

2 3 4 5

6 7 8 9 10 11

Stag e 2 tree using the above mentio n e d proce d u r e is as follows:

172
1

6 3

7 8 4

10

11

Exa m p l e 2:

Const r u c t a uniqu e bina ry tree from the given fores t.

1 7

2 3 8 9 10

4 5 6 11 12 13
0

Solution:

Stage 1 tree using the above mentioned procedure is as follows:

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

Se ar c h an d Traver s a l Tec h n i q u e s for m- ary tre e s :


Search involves visiting nodes in a tree in a systematic manner, and may or may not result into a visit
to all nodes. When the search necessarily involved the examination of every vertex in the tree, it is
called the traversal. Traversing of a tree can be done in two ways.

1. Dept h first sea rc h or trave r s al.


2. Brea d t h first sea rc h or trave r s a l.

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.

To illustr a t e this let us conside r the tree show n below.

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.

So the solution pat h to the goal is S, C, F, H and G and the stat e s


consid e r e d wer e in orde r S, A, D, E, B, C, F, H, J, G.

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.

To elimina t e this keep a list of stat e s previou sly visite d, and


neve r per mit sear c h to ret u r n to any of the m.

2. We canno t come up with short e s t solution to the proble m .

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.

To illustrate this let us consider the following tree:

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.

7.8. Sparse Matrices:

A sparse matrix is a two–dimensional array having the value of majority elements as


null. The density of the matrix is the number of non-zero elements divided by the
total number of matrix elements. The matrices with very low density are often good
for use of the sparse format. For example,

0 0 0 5
 
0 2 0 0
A  1 3 0 0
 
0 0 4 0 

As far as the storage of a sparse matrix is concerned, storing of null elements is


nothing but wastage of memory. So we should devise technique such that only non-
null elements will be stored.

The matrix A produces:

(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.

In large number of applications, sparse matrices are involved. One approach is to


use the linked list.

The pro g r a m to repr e s e n t spar s e matrix:

/* 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 . */

# includ e <s t dio.h >


# includ e <co nio.h >

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

CHADALAWADA RAMANAMMA ENGINEERING COLLEGE


(AUTONOMOUS)
Chadalawada Nagar, Renigunta Road, Tirupati – 517 506

Department of Computer Science and Engineering

You might also like