Unit 1 Merged
Unit 1 Merged
1.0 INTRODUCTION
The word “Algorithm” comes from the Persian author Abdullah Jafar
Muhammad ibn Musa Al-khowarizmi in ninth century, who has given the
definition of algorithm as follows:
An Algorithm is a set of rules for carrying out calculation either by hand
or on a machine.
An Algorithm is a well defined computational procedure that takes input
and produces output.
An Algorithm is a finite sequence of instructions or steps (i.e. inputs) to
achieve some particular output.
5
Introduction to
Algorithm 1.1 OBJECTIVES
After studying this unit, you should be able to:
In this unit we will examine several issues related to basics of algorithm: starting
from how to write a Pseudo-code for algorithm, mathematical induction,
time and space complexity and Recurrence relations. Time and space
complexity will be further discussed in detail in unit 2.
Suppose M is an algorithm, and suppose n is the size of the input data. The time and
space used by the algorithm M are the two main measures for the efficiency
of M. The time is measured by counting the number of key operations, for
example, in case of sorting and searching algorithms, the number of
comparisons is the number of key operations. That is because key operations
are so defined that the time for the other operations is much less than or at
most proportional to the time for the key operations. The space is measured
by counting the maximum of memory needed by the algorithm.
The complexity of an algorithm M is the function f(n), which give the running time
and/or storage space requirement of the algorithm in terms of the size n of the
input data. Frequently, the storage space required by an algorithm is simply a
multiple of the data size n. In general the term “complexity” given anywhere
simply refers to the running time of the algorithm. There are 3 cases, in
general, to find the complexity function f(n):
6
The analysis of the average case assumes a certain probabilistic
Basics of an Algorithm
distribution for the input data; one such assumption might be that all
possible permutations of an input data set are equally likely. The Average
case also uses the concept of probability theory. Suppose the numbers
…… occur with respective probabilities Then the expectation or
average value of E is given by
Best case: Clearly the best case occurs when x is the first element in the array
is . In this case
A. That
Worst case: Clearly the worst case occurs when x is the last element in the
array A or is not present in given array A (to ensure this we have to search
entire array A till last element). In this case, we have
.
7
Introduction to
Algorithm Average case: Here we assume that searched element appear array A, and it
is equally likely to occur at any position in the array. Here the number of
comparisons can be any of numbers , and each
number occurs with the probability then
Asymptotic notation gives the rate of growth, i.e. performance, of the run
time for “sufficiently large input sizes” and is not a measure
of the particular run time for a specific input size (which should be done
empirically). O-notation is used to express the Upper bound (worst case); Ω-
notation is used to express the Lower bound (Best case) and Θ- Notations is
used to express both upper and lower bound (i.e. Average case) on a function.
1. Divide-and-Conquer
2. Greedy method
3. Dynamic Programming
4. Backtracking
5. Branch-and-Bound
8
In this section we will briefly describe these techniques with appropriate
Basics of an Algorithm
examples.
10
any programming language. Pseudo-code cannot be compiled nor executed,
Basics of an Algorithm
and not following any syntax rules.
The first line of a function consists of the name of the function followed
parentheses, in parentheses we pass the parameters of the function. The
parameters may be data, variables, arrays, and so on, that are available to the
function. In the above algorithm, The parameters are the three input values,
and the output parameter, , that is assigned the maximum of the
three input values
11
Introduction to
Algorithm
5.
Use operator for assignments.
Ex:
12
Now we have to
prove that it is true
for (n+1).
Statement1:
Statement2:
Statement3:
…….
……….
Statement n:
…….
………
Example1: Prove the proposition that “The sum of the first n positive
Proof:
(Base Step): We must show that the given equation is true for
i.e. this is true.
Hence we proved “S(1) is true”.
(Induction Step):
that is ;
Basics of an Algorithm
13
Introduction to
Consider
Algorithm
S (n 1 2 3 ........ n (n 1)
1)
P(n) (n 1)
n(n 1)
2 (n 1)
(n 1)(n 2) (n 1)[(n 1) 1]
2 2
Hence S(n+1) is also true whenever S(n) is true. This implies that
(Induction Step):
1)
6
(n 1) 2n2 n 6n 6
6
(n 1)(n 2)(2n 3)
6
(n 1)(n 2) 2(n 1) 1
6
Which is P(n+1).
Hence P(n+1) is also true whenever P(n) is true P(n) is true for all n.
14
In the subsequent section we will look at some formulae which are usually
Basics of an Algorithm
used in mathematical proof.
:
Given a arithmetic Series
where
For
I) (when
II) (when
III)
Logarithmic Formulae
The following logarithmic formulae are quite useful for solving recurrence
relation.
1.
2.
3.
4.
5.
6.
15
Introduction to
Algorithm 7.
Time Complexity
The time , taken by a program P, is the sum of the Compile time & the Run
(execution) time. The Compile time does not depends on the instance
characteristics (i.e. no. of inputs, no. of outputs, magnitude of inputs,
magnitude of outputs etc.).
1. Algorithm X (a,b,c)
S:= 0
For i = 1 to n do
S = S + a [i];
Return S;
16
Here the problem instance is characterized by value of n, i.e., number of
Basics of an Algorithm
elements to be summed.
ADD, SUB, MUL, DIV is a functions whose values are the numbers of
performed when the code for P is used on an instance with characteristics n.
Generally, the time complexity of an algorithm is given by the no. steps
taken by the algorithm to complete the function it was written for.
The number of steps is itself a function of the instance characteristics.
17
Introduction to
To determine the running time of this program, we have to count the number
Algorithm
of statements that are executed in this procedure. The code at line 1 executes
1 time, at line 2 the for loop executes Line 3 executes
and line 4 executes 1 time. Hence
Example1
Frequency Total steps
Add(a, b, c, m, n) −
−
For i = 1 to m do m m
For j = 1 to n do m(n) m.n
c[i, j] = a[i, j] + b[i, j] mn mn
− −
2mn+m
Best Case: It is the minimum number of steps that can be executed for
the given parameter.
Worst Case: It is the maximum no. of steps that can be executed for the
given parameter.
Average case: It is the Average no. of steps that can be executed for the
given parameter.
Best Case: Suppose we open a dictionary and luckily we get the meaning of a
word which we are looking for. This requires only one step (minimum
possible) to get the meaning of a word.
Worst case: Suppose you are searching a meaning of a word and that word is
either not in a dictionary or that word takes maximum possible steps (i.e. now
no left hand side or right hand side page is possible to see).
Average Case: If you are searching a word for which neither a Minimum
(best case) nor a maximum (worst case) steps are required is called average
case. In this case, we definitely get the meaning of that word.
To understand the concept of Best, Average and worst case and the where to
use basic notations O, Ω, and Θ, consider again another example known as
Binary search algorithm. A Binary search is a well known searching
algorithm which follows the same concept of English dictionary.
To understand a Binary search algorithm consider a sorted linear
array , Suppose you want either to find(or search) the location
LOC of a given element (say ) in the given array A (successful search) or to
send some message, such as LOC=0, to indicate that does not appear in
A(Unsuccessful search). A Binary search algorithm is an efficient technique
for finding a position of specified value (say x) within a sorted array A. The
best example of binary search is “dictionary”, which we are using in our
daily
18
life to find the meaning of any word (as explained earlier). The Binary search
Basics of an Algorithm
algorithm proceeds as follow:
1) Begin with the interval covering the whole array; binary search
repeatedly divides the search interval (i.e. Sorted array A) in half.
2) At each step, the algorithm compares the given input key (or search)
value x with the key value of the middle element of the array A.
3) If it match, then a searching element x has been found so its index, or
position, is returned. Otherwise, if the value of the search element x is
less than the item in the middle of the interval; then the algorithm repeats
its action on the sub-array to the left of the middle element or, if the
search element x is greater than the middle element‟s key, then on the
sub-array to the right.
4) We repeatedly check until the searched element is found
(i.e. ) or the interval is empty, which indicates x is “not
found”.
Best Case: Clearly the best case occurs when you divide the array 1st time
and you get the searched element . This requires only one step
(minimum possible step). In this case, the number of comparison,
.
Worst case: Suppose you are searching a given key and that is
either not in a given array or to search that element takes
maximum possible steps (i.e. now no left hand side or right hand side
elements in array A is possible to see). Clearly the worst case occurs, when
is searched at last.
Let us assume for the moment that the size of the array is a power of 2, say
. Each time when we examine the middle element, we cut the size of
the sub-array is half. So before the 1st iteration size of the array is .
st
After the 1 iteration size of the sub-array of our interest is : .
nd
After the 2 iteration size of the sub-array of our interest is :
……
…….
After the .iteration size of the sub-array of our interest is :
So we stop now for the next iteration. Thus we have at most
iterations.
Average Case: If you are searching given key for which neither a
Minimum (best case) nor a maximum (worst case) steps are required is called
average case. In this case, we definitely get the given key in the array A. In
this case also
19
Introduction to
The following table summarizes the time complexity of Binary search in
Algorithm
various cases:
These notations are used to describe the Running time of an algorithm, in terms of
functions, whose domains are the set of natural numbers,
N = {1, 2, ……}. Such notations are convenient for describing the worst case
running time function. T(n) (problem size input size).
The complexity function can be also be used to compare two algorithms P and Q that
perform the same task.
: n ≥ n0
20
The intuition behind O- notation is shown in Figure 1.
Basics of an Algorithm
C.g(n
f(n) No
Matter
F(n)
Figure 1
n →n0
Figure 1
For all values of n to the right of n0, the value of f(n) is always lies on or
below
Solution:
Remark: The value of C and is not unique. For example, to satisfy the
above equation (1), we can also take . So depending on the
value of C, the value of is also changes. Thus any value of C and which
satisfy the given inequality is a valid solution.
; Let C=3
21
Introduction to
Algorithm
Value of n
6 3
15 24
27 81
For ; we get
……. (1)
There is no value of C and , which satisfy this equation (1). For example,
if you take , then to contradict this inequality you can take any value
greater than C, that is . Since we do not found the required constant
C and to satisfy (1). Hence
(v) Do yourself.
:
Theorem
: n ≥ n0
22
Basics of an Algorithm
f(n) No
f(n) = Ω g(m)
Matter
n0
n
Figure 2
Note that for all values of f(n) always lies on or above g(n).
: show that
Solution:
Hence .
23
Introduction to
Let then there exist a
Algorithm
positive constant C and such that
Thus .
Thus
Let
(v) Do yourself.
Let and are two positive functions , each from the set of natural
numbers (domain) to the positive real numbers. In some cases, we have
24
(Note that this inequality (1) represents two conditions to be satisfied
Basics of an Algorithm
simultaneously viz and
c2g(n)
f(n)
c1g(n)
f(n) = (g(n))
n0
n Figure 3
Note that for all values of n to the right of the n0 the value of f(n) lies at or
above C1g(n) and at or below C2.g(n).
: show that
Hence
Let
Thus .
(iii) Do yourself.
If
Theorem1:
Proof:
for
Let us assume
Then .
If
Theorem2:
Proof:
26
Since
Basics of an Algorithm
Theorem3: If
…….(1)
(i)
(ii)
Solution:
(i) Here , So
by Theorem1,2 and 3:
, and .
(ii) , So by
Theorem1,2 and 3:
, and .
c) d) none of these
Q.2: What is the running time to retrieve an element from an array of size n
(in worst case):
c) d) none of these
c) d)
27
Introduction to
Algorithm ………
c) d)
g)
k) where
28
1.9 RECURRENCE Basics of an Algorithm
There are two important ways to categorize (or major) the effectiveness and
efficiency of algorithm: Time complexity and space complexity. The time
complexity measures the amount of time used by the algorithm. The space
complexity measures the amount of space used. We are generally interested
to find the best case, average case and worst case complexities of a given
algorithm. When a problem becomes “large”, we are interested to find
asymptotic complexity and O (Big-Oh) notation is used to quantify this.
1. Basic step: Here we have one or more constant values which are used
to terminate recurrence. It is also known as initial conditions or base
conditions.
This formula says that “by adding two previous sequence (or
term) we can get the next term”.
For example
Let us consider some recursive algorithm and try to write their recurrence
relation. Then later we will learn some method to solve these recurrence
relations to analyze the running time of these algorithms.
Algorithm: FACT(n)
1: if
3: else
4:
5:
Thus we can write a recurrence relation for the algorithm FACT as:
(We can also write some constant valve instead of writing 0 and 1, that is
Since when n=1 (base case), the FACT at line 1 perform one
comparison and one return statement at line 2. Therefore
30
Where b is a some constant, and for line 4 (when Basics of an Algorithm
it is The reason for writing
constants b and c , instead of writing exact value (here 0 and 1) is that, we
always interested to find “asymptotic complexity” (i.e. problem size n is
“large”) and O(big “Oh) notation is used (for getting “Worst case”
complexity) to quantify this.
In Section 1.81-1.83 of this unit, we will learn some methods to solve these
recurrence relations) .
Algorithm2: Example(n)
1: if
3:
4:
5:
5:
Algorithm3:
1: if
3:
4:
5:
31
Introduction to
The base case is reached when The algorithm2
Algorithm
performs one comparison and one return statement. Therefore,
, where is some constant.
When the algorithm3 performs TWO recursive calls
each with the parameter at line 4, and some constant
number of basic operations. Thus we obtain the recurrence
relation as:
Algorithm4:
1: if
3:
4:
5:
6:
7:
Example5: The worst case running time T(n) of Binary Search procedure
(explained earlier) is given by the recurrence:
32
2. Iteration Method (unrolling and summing)
Basics of an Algorithm
3. The Recursion-tree method
4. Master method
Or
Thus
Solution: Here
34
= ………..
Basics of an Algorithm
Solution:
Solution: Here
(By substituting
35
Introduction to
Algorithm [ Using log property ]
a) To make a recursion tree of a given recurrence (1), First put the value of
at root node of a tree and make a of child node of this
root value Now tree will be looks like as:
………
Figure-a
… (2)
36
Basics of an Algorithm
From equation (2), now will be the value of node
having branch (child nodes) each of size T(n/b). Now each
………
…. ……
Figure-b
c) In this way you can expend a tree one more level (i.e. up to (at least)
2 levels).
Step2: (a) Now you have to find per level cost of a tree. Per level cost is the
sum of the cost of each node at that level. For example per level cost at
(b) Now the total (final) cost of the tree can be obtained by taking the sum of
costs of all these levels.
). This is
also called Column-Sum.
37
Introduction to
Algorithm
2. The number of child of a Root Node is equal to the value of a. (Here the
value of So recursion tree be looks like as:
Figure-a
… (2)
Figure-b
38
Basics of an Algorithm
c) In this way, you can extend a tree up to Boundary condition
(when problem size becomes 1). So the final tree will be looks like:
…..................n
………… n
…… n
…… n
…...................................................................n
1 1 1 ……………… ………………. 1 1 …. n
Now we find the per level cost of a tree, Per-level cost is the sum of the costs
within each level (called row sum). Here per level cost is For example:
per level cost at depth 2 in figure-c can be obtained as:
Then total cost is the sum of the costs of all levels (called column sum),
which gives the solution of a given Recurrence. The height of the tree is
To find the sum of this series you have to find the total number of terms in
this series. To find a total number of terms, you have to find a height of a
tree.
Height of tree can be obtained as follow (see recursion tree of figure c): you
start a problem of size n, then problem size reduces to , then and so
on till boundary condition (problem size 1) is not reached. That is
39
Introduction to
Algorithm
Hence total cost in equation (3) is
).
Solution: We always omit floor & ceiling function while solving recurrence.
Thus given recurrence can be written as:
Figure-a
Figure-b
40
Basics of an Algorithm
c) In this way, you can extend a tree up to Boundary condition (when
problem size becomes 1). So the final tree will be looks like:
……. n
……… n
…….. n
……………… ………………..
………….
T(1) T(1)
T(1) T(1)
(*)
(**)
41
Introduction to
From equation (*) and
Algorithm
(**), thus we can
write:
Remark: If
Solution:
Figure-a
Figure-b
42
So the final tree will be looks like:
Basics of an Algorithm
1 …….. 1
………
..……..
.
…………………
1 1 1 1………. ………… 1 1 1 1 ……
Hence Total Cost of the tree in figure (c) can be obtained by taking column
sum upto the height of the tree.
a)
{ if
//if n is even
}
43
Introduction to
Algorithm
b)
{ if
a)
b.
c.
d.
44
Theorem1: Master Theorem
Basics of an Algorithm
The Master Method requires memorization of the following 3 cases; then the
solution of many recurrences can be determined quite easily, often without
using pencil & paper.
Case2: If , then .
45
Introduction to
Algorithm
Examples of Master Theorem
satisfied for
.
Example4: Can the Master method be applied to solve recurrence
Solution:
Here a = 2 b = 2
Now
positive constant ∊ .
The ratio = = logn ; is asymptotically less than for any
So, the recurrence falls into the gap between case 2 and case 3. Thus, the
master theorem can not apply for this recurrence.
Solution:
46
The master method gives us a = 7, b = 2 f(n) = Basics of an Algorithm
which gives
where
a) b)
c) d)
a) b) c) d)
a) b) c) d)
Q.6: Use Mater Theorem to give the tight asymptotic bounds of the following
recurrences:
a.
b.
c.
d.
e.
f.
1.10 SUMMARY
1. “Analysis of algorithm” is a field in computer science whose overall
goal is an understanding of the complexity of algorithms (in terms of
time Complexity), also known as execution time & storage (or space)
requirement taken by that algorithm.
2. An Algorithm is a well defined computational procedure that takes
input and produces output.
48
3. An algorithm is a finite sequence of steps, each of which has a clear Basics of an Algorithm
meaning and can be performed with a fine amount of effort in an
finite length of time.
10. O-notation: Given functions f(n) and g(n), we say that f(n) is O(g(n))
if there exist two positive constants c > 0 and
such that f(n) ≤ cg(n) for all n, n Big-Oh notation
gives an upper bound on the growth rate of a function.
11. -notation: Given functions f(n) and g(n), we say that f(n) is (g(n)) if
there exist 2 positive constants c > 0 and such that f(n) cg(n)
for all n, n Big-Omega notation gives a lower bound on the growth
rate of a function.
12. Θ-notation: Let f(n) and g(n) be two asymptotically positive real-
valued functions. We say that f(n) is Θ(g(n)) if there is an integer and
two positive real constants and such that g(n) g(n) for
all n
13. When an algorithm contains a recursive call to itself, its running time
can often be described by a recurrence. A recurrence relation is an
equation or inequality that describes a function in terms of its value on
smaller inputs. For example, a recurrence relation for Binary Search
procedure is given by:
49
Introduction to
14. There are three basic methods of solving the recurrence relation:
Algorithm
1. The Substitution Method
16. In master method you have to always compare the value of with
to decide which case is applicable. If is asymptotically
smaller than , then case1 is applied. If is asymptotically
same as , then case2 is applied. If is asymptotically
larger than , and if
then case3 is applied.
1.11 SOLUTIONS/ANSWERS
Check Your Progress 1
Answer 5:
50
Dynamic Programming All Pair Shortest Path Problem Basics of an Algorithm
(Floyed Algorithm), Chain Matrix
multiplication.
Answer 7:
Answer 8:
There are 3 basic asymptotic notations (O,Ω and Θ) used to express the
time complexity of an algorithm.
of a function
It express upper bound
(Big omega) there exist a positive constants and
notation
such that for all }.
for all }. It
express both upper and lower bound of a function
Solution 9:
51
Introduction to
Algorithm
Time taken by a program is the sum of the compile time and the run
time. In time complexity, we consider run time only. The time required
by an algorithm is determined by the number of elementary operations.
Solution 10:
(a)
Hence
2 and
For C =
)
52
Basics of an Algorithm
(c) );
(d)
(e)
Clearly n = O(
53
Introduction to
Algorithm
1) L.H.S inequality:
[Assume
and n ≥ 1
2) R.H.S. inequality
and n ≥ 1
(by definition of Θ)
not implies
k)
Solution 1: a)
At every step the problem size reduces to half the size. When the power
is an odd number, the additional multiplication is involved. To find a
time complexity of this algorithm, let us consider the worst case, that is
we assume that at every step additional multiplication is needed. Thus
total number of operations T(n) will reduce to number of operations for
n/2, that is T(n/2) with three additional arithmetic operations(In odd
power case: 2 multiplication and one division). Now we can write:
55
Introduction to
Algorithm
b)
a)
Thus
56
Solution 3 (a) : The recursion tree for the given recurrence is:
Basics of an Algorithm
Figure a
Figure b
……. n
……… n
…….. n
……………… ………………..
We have
57
Introduction to
Algorithm
Solution (d)
T=(n) = T
……. n
……… (7/8)n
……..
………………
T(1)
58
Check Your Progress 3:
Basics of an Algorithm
(Objective Questions)
Case2: If , then .
a) In a recurrence , a = 4, b=2,
. Now compare
, where . By Master Theorem
case1 we get
b) : ; in which
Now compare
ince . Thus By Master Theorem (case 2), we
get
; in which
Now compare
Since where ∈=1. Case3 of
Master method may be applied.
Now check (Regularity Condition)
satisfie
d for
d) T(n)= 4T + n2
Here a = 4 b = 2 f(n)= n2 =
; Now compare .
Since f(n)= n2 = . Hence Case3 of Master method
may be applied.
59
Introduction to
Algorithm Now check (Regularity Condition):
satisfied for
since so now we can apply mater method (case 3).
.
e)
Here a = 4 b = 3 f(n) =
Now
; Case1 is applied.
T(n) = Ѳ(
60
1.12 FURTHER READINGS Basics of an Algorithm
61
Introduction to Algorithm UNIT 2: ASYMPTOTIC BOUNDS
Structure Page Nos.
2.0 Introduction 62
2.1 Objective 63
2.2 Asymptotic Notations 63
2.2.1 Theta Notation ( )
2.2.2 Big Oh Notation (O)
2.2.3 Big Omega Notation ( )
2.2.4 Small o Notation (o)
2.2.5 Small Omega Notation ( )
2.3 Concept of efficiency analysis of algorithm 76
2.4 Comparison of efficiencies of algorithms 79
2.5 Summary 80
2.6 Model Answers 81
2.7 Further Readings 84
2.0 INTRODUCTION
62
Asymptotic Bounds
2.1 OBJECTIVES
After studying this unit, you should be able to:
Asymptotic notations
Worst case, best case and average case analysis
Comparative analysis of Constant, Logarithmic, Linear, Quadratic and
Exponential growth of an algorithm
Before staring the discussion of asymptotic notations, let us see the symbols that will
be used through out this unit. They are summarized in the following table.
Symbol Name
Theta
Big Omega
Belongs to
Small Omega
for all
there exist
=> Implies
An algorithm is set of instruction that takes some input and after computation it
generates an output in finite amount of time. This can be evaluated by a variety of
criteria and parameters. For performance analysis of an algorithm, following two
complexities measures are considered:
Space Complexity
Time Complexity
Before starting with an introduction to asymptotic notations let us define the term
asymptote. An asymptote provides a behavior in respect of other function for varying
value of input size. An asymptote is a line or curve that a graph approaches but does
not intersect. An asymptote of a curve is a line in such a way that distance between
curve and line approaches zero towards large values or infinity.
63
Introduction to Algorithm
The figure 1 will illustrate this.
Figure:- 1
In the Figure 1, curve along x-axis and y axis approaches zero. Also the curve will not
intersect the x-axis or y axis even for large values of either x or y.
Let us discuss one more example to understand the meaning of asymptote. For
example x is asymptotic to x+1 and these two lines in the graph will never intersect as
depicted in following Figure 2.
x+1
Figure:- 2
In Figure 2, x and x+1 are parallel lines and they will never intersect with each other.
Therefore it is called as x is asymptotic to x+1.
The concept of asymptote will help in understanding the behavior of an algorithm for
large value of input.
Now we will discuss the introduction to bounds that will be useful to understand the
asymptotic notations.
Lower Bound: A non empty set A and its subset B is given with relation ≤. An
element a A is called lower bound of B if a ≤ x x B (read as if a is less than
equal to x for all x belongs to set B). For example a non empty set A and its subset B
is given as A={1,2,3,4,5,6} and B={2,3}. The lower bound of B= 1, 2 as 1, 2 in the
set A is less than or equal to all element of B.
64
A bound (upper bound or lower bound) is said to be tight bound if the inequality is Asymptotic Bounds
less than or equal to (≤) as depicted in Figure 3.
Similarly a bound (lower bound or upper bound) is said to be loose bound if the
inequality is strictly less than (< ) as depicted in Figure 4.
B
A
B
Loose Bound
Tight Bound A
x x
For example in figure 3, distance between lines A and B is less as B ≤ A. For large
value of x, B will approach to A as it is less than or equal to A.
In Figure 4, A < B i.e. distance between A and B is large. For example A < B, there
will be distance between A and B even for large value of x as it is strictly less than
only.
We also require the definition of bounded above or bounded below and bounded
above & below both to understand the asymptotic notations.
Bounded above: Let A is non empty set and B is non empty subset of A. Bounded
from above on B i.e supremum or least upper bound on B is defined as an upper
bound of B which is less than or equal to all upper bounds of B. For example a non
empty set A and its subset B is given as A={1,2,3,4,5,6} and B={2,3}. The upper
bound of B= 3,4,5,6 as 3,4,5,6 in the set A is greater than or equal to all element of B.
Least upper bound of B is 3 i.e 3 is less than equal to all upper bounds of B.
Bounded below: Let A is non empty set and B is non empty subset of A. Bounded
from below on B i.e infimum or greatest lower bound on B is defined as a lower
bound of B which is greater than or equal to all lower bounds of B. For example a
non empty set A and its subset B is given as A={1,2,3,4,5,6} and B={2,3}. The lower
bound of B= 1, 2 as 1, 2 in the set A is less than or equal to all element of B. Greatest
lower bound of B is 2 i.e. 2 is greater than equal to all lower bounds of B.
To study the analysis of an algorithm and compute its time complexity we will be
computing the total running time of an algorithm. Total running time of an algorithm
is dependent on input size of the problem. Hence complexity expression will always
be a function in term of input size. Hence we also require understanding the bounds in
respect of function.
65
In respect of function defined on non empty set X , bounded above is written as
Introduction to Algorithm f(x) ≤ A x X then we say function is bounded above by A. It is read as
function
for all elements in the set X is less than or equal to A.
A function is said to be bounded if it has both bounds i.e bounded above and
below both. It is written as A ≤ f(x) ≤ Bx X.
The bounded above is depicted by figure 5 and bounded below by figure 6. Bounded
above and below both is illustrated by figure 7.
A
f(x) f(x)
A
B
f(x)
Both bounds
In figure 5, bounded above indicates that the value of f(x) will never exceed A. It
means we know the largest value of function f(x) for any input value for x. Similarly
in figure 6 bounded below provide the smallest value of function f(x) for any input
value of x. In figure 7 we get the information for smallest and largest value both. The
function f(x) will be in the range A and B i.e the smallest value for function f(x) is A
and the largest value for f(x) is B. Here we know the both the values A and B i.e
minimum and maximum value for f(x) for any input value of x.
66
Now, Let us discuss the formal definitions of basic asymptotic notation which are Asymptotic Bounds
named as (Theta), O(Big Oh), (Big Omega),o(Small Oh), (Small Omega).
Let g(n) be given function i.e a function in terms of input size n. In the following
section we will be discussing various asymptotic notations to find the solution
represented by function f(n) belongs to which one of basic asymptotic notations.
It can be written as f(n)= (g(n)) or f(n) (g(n)), here f(n) is bounded both above
and below by some positive constant multiples of g(n) for all large values of n. It is
described in the following figure 8.
c2g(n)
f(n)
c1g(n)
n0 n
Figure:- 8 (n)
In the figure 8 function f(n) is bounded below by constant c1 times g(n) and above by
constants c2 times g(n). We can explain this by following examples:
Example 1:
To show that 3n+3 = (n) or 3n+3 (n) we will verify that f(n) g(n) or not with
the help of the definition i.e
(g(n)) = {f(n): if there exist positive constant c1,c2 and n0 such that 0≤c1g(n)≤f(n)
≤c2g(n) for all n, n n0}
In the given problem f(n)= 3n+3 and g(n)=n to prove f(n) g(n) we have to find c1,c2
and n0 such that 0≤c1g(n)≤f(n) ≤c2g(n) for all n, n n0
To verify 0≤c1g(n)≤f(n)
We can write f(n)=3n+3 3n (again write f(n) in terms of g(n) such that
mathematically ineqaulity should be true)
i.e we are able to find, c1=3, c2=6 n0=1 such that 0≤c1g(n)≤f(n) ≤c2g(n) for all n, n n0
So, f(n)= (g(n)) for all n 1
Example 2:
To show that 10n2+4n+2= (n2) or 10n2+4n+2 (n2) we will verify that f(n) g(n)
or not with the help of the definition i.e
(g(n)) = {f(n): if there exist positive constant c1,c2 and n0 such that 0≤c1g(n)≤f(n)
≤c2g(n) for all n, n n0}
In the given problem f(n)= 10n2+4n+2 and g(n)= n2 to prove f(n) g(n) we have
to find c1,c2 and n0 such that 0≤c1g(n)≤f(n) ≤c2g(n) for all n, n n0
O(Big Oh) Notation: mean `order at most' i.e bounded above or it will give
maximum time required to run the algorithm.
For a function having only asymptotic upper bound, Big Oh „O‟ notation is used.
Let a given function g(n), O(g(n))) is the set of functions f(n) defined as
68
O(g(n))={f(n): if there exist positive constant c and n0 such that 0≤f(n) ≤cg(n) for all Asymptotic Bounds
n, n n0}
f(n)= O(g(n)) or f(n) O(g(n)), f(n) is bounded above by some positive constant
multiple of g(n) for all large values of n. The definition is illustrated with the help of
figure 9.
cg(n)
f(n)
n0 n
Figure:- 9 O(n)
In this figure9, function f(n) is bounded above by constant c times g(n). We can
explain this by following examples:
Example 3:
To show 3n2+4n+6=O (n2) we will verify that f(n) g(n) or not with the help of the
definition i.e O(g(n))={f(n): if there exist positive constant c and n0 such that 0≤f(n)
≤cg(n) for all n, n n0}
f(n)= 3n2+4n+6
g(n)= n2
Example 4:
To show 5n+8=O(n) we will verify that f(n) g(n) or not with the help of the
definition i.e O(g(n))={f(n): if there exist positive constant c and n0 such that 0≤f(n)
≤cg(n) for all n, n n0}
f(n)=5n+8
g(n)=n
(Big Omega): mean „order at least' i.e minimum time required to execute the
algorithm or have lower bound
f(n)= (g(n)) or f(n) (g(n)), f(n) is bounded below by some positive constant
multiple of g(n) for all large values of n. It is described in the following figure
10.
f(n)
cg(n)
n0 n
Figure:- 10 (n)
In this figure 10, function f(n) is bounded below by constant c times g(n). We can
explain this by following examples:
Example 5:
To show 2n2+4n+6= (n2) we will verify that f(n) g(n) or not with the help of the
definition i.e (g(n)) ={f(n): if there exist positive constant c and n0 such that 0≤
cg(n) ≤f(n) for all n, n n0}
f(n)= 2n2+4n+6
g(n)= n2
Example 6:
To show n3= (n2) we will verify that f(n) g(n) or not with the help of the definition
i.e (g(n)) ={f(n): if there exist positive constant c and n0 such that 0≤ cg(n) ≤f(n) for
all n, n n0}
f(n)= n3
g(n)= n2
We can write
f(n)= n3
0≤n2≤ n3 for n 0
c=1 for all n n0, n0=0
o(small o) Notation:
For a function that does not have asymptotic tight upper bound, o (small o) notation is
used. i.e. It is used to denote an upper bound that is not asymptotically tight.
Let a given function g(n), o (g(n))) is the set of functions f(n) defined as
o (g(n)) = {f(n): for any positive constant c there exist a constant n0 > 0 such that
0≤f(n)< cg(n) for all n n0}
71
Introduction to Algorithm
f(n)= o(g(n)) or f(n) o (g(n)), f(n) is loosely bounded above by all positive constant
multiple of g(n) for all large n. It is illustrated in the following figure 11.
cg(n)
f(n)
n0 n
Figure:-11 o(n)
In this figure 11, function f(n) is loosely bounded above by constant c times g(n). We
can explain this by following example:
Example 7:
To show 2n+4=o(n2) we will verify that f(n) g(n) or not with the help of the
definition i.e o (g(n)) = {f(n): for any positive constant c there exist a constant n0 >
0 such that 0≤f(n)< cg(n) for all n n0}
f(n)=2n+4 , g(n)= n2
Hence, f(n)=o(g(n))
Example 8:
To show 2n=o(n2) we will verify that f(n) g(n) or not with the help of the definition
i.e o (g(n)) = {f(n): for any positive constant c there exist a constant n0 > 0 such that
0≤f(n)< cg(n) for all n n0}
f(n)=2n , g(n)= n2
Hence, f(n)=o(g(n))
For a function that does not have asymptotic tight lower bound, notation is used. i.e.
It is used to denote a lower bound that is not asymptotically tight.
Let a given function g(n). (g(n))) is the set of functions f(n) defined as
(g(n)) = {f(n): for any positive constant c > 0 there exist a constant n0 > 0 such that
0≤ cg(n) < f(n) for all n n0}
f(n)= (g(n)) or f(n) (g(n)), f(n) is loosely bounded below by all positive
constant multiple of g(n) for all large n. It is described in the following figure 11.
f(n)
cg(n)
n0 n
Figure:-11 (n))
In this figure function f(n) is loosely bounded below by constant c times g(n).
Following example illustrate this notation:
Example 9:
To show 2n2+4n+6= (n) we will verify that f(n) g(n) or not with the help of the
definition i.e (g(n)) = {f(n): for any positive constant c > 0 there exist a constant n0
> 0 such that 0≤ cg(n) < f(n) for all n n0}
f(n)= 2n2+4n+6
g(n)= n
f(n)= 2n2+4n+6
73
Introduction to Algorithm cn < 2n2+4n+6 for any c >0 , for all n n0, n0=1
i.e we can find, c=1 , n0=1
Example 10:
To show 2n3+3n2+1= (n) we will verify that f(n) g(n) or not with the help of the
definition i.e (g(n)) = {f(n): for any positive constant c > 0 there exist a constant n0
> 0 such that 0≤ cg(n) < f(n) for all n n0}
f(n)= 2n3+3n2+1
g(n)= n
f(n)= 2n3+3n2+1
cn < 2n3+3n2+1 for any c >0 , for all n n0, n0=1
i.e we can find, c=1 , n0=1
1. scanf(“%d”,&n);
2. printf(“Enter element for an array”);
3. for(i=0;i<n;i++)
4. scanf(“%d”,&a[i]);
74
Asymptotic Bounds
Line Number Number of times
1 1
2 1
3 n
4 n-1
f(n)= 1+1+n+(n-1)
f(n)=2n+1
Now to compute the complexity for the above construct of an algorithm, let us find
the bounds for above function f(n) i.e 2n+1.
f(n)= 2n+1
g(n)= n
f(n)= 2n+1
0≤n≤ 2n+1 for n 0
c=1 for all n n0, n0=0
For this construct complexity will be f(n)= O(n), f(n)= (n), f(n)= (n).
However, we will generally be most interested in the Big Oh time analysis as this
analysis can lead to computation of maximum time required for the algorithm to solve
the given problem.
75
In the next section, we will discuss about concept of efficiency analysis of an
Introduction to Algorithm algorithm.
b) Time Complexity
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
c) Space Complexity
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
If we are given an input to an algorithm we can exactly compute the number of steps
our algorithm executes. We can also find the count of the processor instructions.
Usually, we are interested in identifying the behavior of our program w.r.t input
supplied to the algorithm. Based on type of input, analysis can be classified as
following:
Worst Case
Average Case
Best Case
76
Asymptotic Bounds
In the worst case - we need to look at the input data and determine an upper bound on
how long it will take to run the program. Analyzing the efficiency of an algorithm in
the worst case scenario speaks about how fast the maximum runtime grow when we
increase the input size. For example if we would like to sort a list of n numbers in
ascending order and the list is given in descending order. It will lead to worst case
scenario for the sorting algorithm.
In average case – we need to look at time required to run the algorithm where all
inputs are equally likely. Analyzing the efficiency of an algorithm speaks about
probabilistic analysis by which we find expected running time for an algorithm. For
example in a list of n numbers to be sorted in ascending order, some numbers may be
at their required position and some may be not in order.
In Best case- Input supplied to the algorithm will be almost similar to the format in
which output is expected. And we need to compute the running time of an algorithm.
This analysis will be referred as best case analysis. For example we would like to sort
the list of n numbers in ascending order and the list is already in ascending order.
For example: Consider the linear search algorithm in which we are required to search
an element from a given list of elements, let‟s say size of the list is n.
Algorithm:
Worst Case: In respect of example under consideration, the worst case is when the
element to be searched is either not in the list or found at the end of the list. In this
case algorithm runs for longest possible time i.e maximum running time of the
algorithm depends on the size of an array so, running time complexity for this case
will be O(n).
Average case: In this case expected running time will be computed based on the
assumption that probability of occurrence of all possible input is equal i.e array
elements could be in any order. This provides average amount of time required to
solve a problem of size n. In respect of example under consideration, element could
be found at random position in the list. Running time complexity will be O(n).
77
Best Case: In this the running time will be fastest for given array elements of size n
Introduction to Algorithm i.e. it gives minimum running time for an algorithm. In respect of example under
consideration, element to be searched is found at first position in the list. Running
time complexity for this case will be O(1).
In most of the cases, average case analysis and worst case analysis plays an important
role in comparison to best case. Worst case analysis defines an upper bound on
running time for any input and average case analysis defines expected running time
for input of given size that are equally likely.
For solving a problem we have more than one solution. Comparison among different
solutions provides which solution is much better than the other i.e which one is more
efficient to solve a problem. Efficiency of algorithm depends on time taken to run the
algorithm and use of memory space by the algorithm. As already discussed, focus
will be on time efficiency rather than space.
For example O(n)= O(n/2)= O(n+2) etc. It is read as order will be defined in terms of
n irrespective of the constant factor like divide by 2 or plus 2 etc. As while
discussing complexity analysis we are interested in order of algorithm complexity.
4. Write an algorithm for bubble sort and write its worst case, average case and
best case analysis.
………………………………………………………………………………………
………………………………………………………………………………………
78
Asymptotic Bounds
2.4 COMPARASION OF EFFICIENCIES OF
AN ALGORITHM
Running time for most of the algorithms falls under different efficiency classes.
For large values of n or as input size n grows, some basic algorithm running time
approximation is depicted in following table. As already discussed, worst case
79
analysis is more important hence O Big Oh notation is used to indicate the value
Introduction to Algorithm of function for analysis of algorithm.
The running time of an algorithm is most likely to be some constant multiplied by one
of above function plus some smaller terms. Smaller terms will be negligible as input
size n grows. Comparison given in above table has great significance for analysis of
algorithm.
2. Write a function for implementing binary search. Also give an expression for
running time complexity in terms of input size n for Worst case, Best case
and average case.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
2.5 SUMMARY
80
Among all worst case analysis is important as it provides the information about Asymptotic Bounds
maximum amount of time an algorithm requires for solving a problem of input size n.
The efficiency of some algorithm may differ significantly for input of the same size.
In this unit, five basic Asymptotic notations are defined: (Theta), O(Big Oh), (Big
Omega),o(Small Oh), (Small Omega).
These notations are used to identify and compare asymptotic order of growth of
function in respect of input size n to express algorithm efficiency.
For visualization of growth of function with respect to input size, comparison among
values of some functions for analysis of algorithm is provided. In this comparison
input size is taken as 20,21,22,23,101,102,103, and 104 for constant, logarithmic, linear,
quadratic and exponential functions.
These notation and comparison for growth of function defined and used here will be
used throughout the design and analysis of an algorithm.
Answers:
1)
(a) Algorithm: An algorithm is set of instructions to be executed for a given input
to solve a problem or generate the required out put in finite amount of time. The
algorithm should solve the problem correctly.
(b) Time complexity: Time complexity of an algorithm tells the amount of time
required to run the algorithm as a function of input size n. Generally it is
expressed using O Big Oh notation which ignores constant and smaller terms.
2). Asymptotic Notation: It is the formal way to speak about function and classify
them. Basic five notations are:
(Theta): Let g(n) be given function. f(n) is the set of function defined as
(g(n))={f(n): if there exist positive constant c1,c2 and n0 such that 0≤c1g(n)≤f(n)
≤c2g(n) for all n, n n0}
O(Big Oh):For a given function g(n), O(g(n))), f(n) is the set of functions defined as
O(g(n))={f(n): if there exist positive constant c and n0 such that 0≤f(n) ≤cg(n) for all
n, n n0}
(Big Omega):For a given function g(n), (g(n))), f(n) is the set of functions
defined as (g(n))={f(n): if there exist positive constant c and n0 such that 0≤ cg(n)
≤f(n) for all n, n n0}
81
o(Small Oh):For a given function g(n), o (g(n))), f(n) is the set of functions defined
Introduction to Algorithm as o (g(n)) = {f(n): for any positive constant c there exist a constant n0 > 0 such that
0≤f(n)< cg(n) for all n n0}
(Small Omega ):For a given function g(n), (g(n))), f(n) is the set of functions
defined as (g(n)) = {f(n): for any positive constant c > 0 there exist a constant n0 >
0 such that 0≤ cg(n) < f(n) for all n n0}
int i,j,temp,flag=true;
{
flag=false
for(j=0; j<n-i-1; j++)
{
if(a[j]>a[j+1])
{
flag=true
82
temp = a[j]; Asymptotic Bounds
a[j] = a[j+1];
a[j+1] = temp;
}
}
Best-case:
When the given data set in an array is already sorted in ascending order the number of
moves/exchanges will be 0, then it will be clear that the array is already in order
because no two elements need to be swapped. In that case, the sort should end, which
takes O(1). The total number of key comparisons will be (n-1) so complexity in best
case will be O(n).
Worst-case:
In this case the given data set will be in descending order that need to be sorted in
ascending order. Outer loop in the algorithm will be executed n-1 times. The number
of exchanges will be 3*(1+2+...+n-1) = 3 * n*(n-1)/2 i.e O(n2). The number of key
2
comparison will be (1+2+...+n-1)= n*(n-1)/2 i.e O(n ). Hence complexity in worst
case will be O(n2).
Average –case:
In this case we have to consider all possible initial data arrangement. So as in case of
worst case ,outer loop will be executed n-1 times. The number of exchanges will be
O(n2). The number of key comparison will be i.e O(n2).So the complexity will be
O(n2).
log n logarithmic
n linear
n2 quadratic
83
Introduction to Algorithm
2) Function for binary search is given below:
For Successful search that is element to be searched is found in the list, running time
complexity for different cases will be as follows:
84
UNIT 3: ANALYSIS OF SIMPLE ALGORITHMS Analysis of simple Algorithms
Structure Page Nos.
3.0 Introduction 85
3.1 Objective 85
3.2 Euclid Algorithm for GCD 86
3.3 Horner‟s Rule for Polynomial Evaluation 88
3.4 Matrix (n x n) Multiplication 90
3.5 Exponent Evaluation 92
3.5.1 Left to Right binary exponentiation
3.5.2 Right to left binary exponentiation
3.6 Searching 95
3.7.1 Linear Search
3.7 Sorting 97
3.8.1 Bubble Sort
3.8.2 Insertion Sort
3.8.3 Selection Sort
3.8 Summary 104
3.9 Model Answers 105
3.10 Further Reading 110
3.0 INTRODUCTION
In the previous unit we have studied about asymptotic notation and efficiency analysis
of algorithm. In the continuation this unit will provide an insight to various categories
of algorithm and their complexity analysis. Algorithms considered for analyzing the
complexity are Euclid‟s algorithm to compute GCD, Matrix Multiplication of square
matrix. Variants of exponent evaluation algorithm and its brute force approach and
the major difference in the order of complexity is discussed. Further searching
algorithm is described and analyzed for various cases like best case, worst case and
average case as described in the Unit2. Then sorting algorithm is categorized on the
basis of storage of input data in primary memory or secondary memory. In this unit
we have discussed only few internal sorting algorithms and their complexity analysis.
3.1 OBJECTIVES
After studying this unit, you should be able to:
85
Introduction to Algorithm 3.2 EUCLID ALGORITHM FOR GCD
Let us take some basic algorithm construct that will be helpful through out this unit
for computing execution time of any algorithm. To compute the same we will count
the number of basic operation and its cost to find total cost of an algorithm.
For example: Sequence of statement
Cost Time
x=x+2; c1 1
a=b; c2 1
Total cost for sequence statement will be = 1 x c1 + 1 x c2
= c1+c2 i.e proportional to constant 1
Cost time
a=b; c1 1
z=2; c2 1
for(i=0;i<n;i++)c3 n+1
{
x= x+2 c4 n
for(j=0;j<n;j++) c5 n x (n+1)
y=y+1 c6 nxn
}
The algorithm for calculating GCD will be explained in two steps. In the first step we
will write pseudo code and in the second step the algorithms will be discussed. This
algorithm can be easily coded into a programming language. Further explanation of
the algorithm is supported through an example.
Let us define GCD (Greatest Common divisor) Problem that you might have already
read earlier or referred somewhere during your school days.
GCD of two non negative, non zero (both) integers i.e. m and n, is the largest integer
that divides both m and n with a remainder of zero. Complexity analysis of an
algorithm for computing GCD depends on which algorithm will be used for GCD
computation. In this section Euclid‟s Algorithm is used to find GCD of two non
negative, both non zero integers, m and n.
86
Step II : Algorithm for Computing GCD(m,n) by Euclid‟s Method
Analysis of simple Algorithms
function gcd(m,n)
{
while (n 0)
{
r= m mod n
m=n
n=r
}
return m
}
In subsequent iterations dividend and divisor are based on what number we get as a
divisor and as a remainder respectively of previous iteration.
Combining above all gives gcd(662,414)=2 which is the last divisor that gives
remainder 0.
Complexity Analysis
In function gcd(m,n), each iteration of while loop has one test condition, one division
and two assignment that will take constant time. Hence number of times while loop
will execute will determine the complexity of the algorithm. Here it can be observed
that in subsequent steps, remainder in each step is smaller than its divisor i.e smaller
than previous divisor. The division process will definitely terminate after certain
number of steps or until remainder becomes 0.
Best Case
If m=n then there will be only one iteration and it will take constant time i.e O(1)
87
Introduction to Algorithm
Worst Case
Average Case
Since m mod n = r such that m = nq + r, it follows that r < n, so m > 2r. So after
every two iterations, the larger number is reduced by at least a factor of 2 so there are
at most O(log n) iterations.
Complexity will be O(log n), where n is either the larger or the smaller number.
The algorithm for evaluating a polynomial at a given point using Horner‟s rule will be
explained in two steps. In the first step we will write pseudo code and in the second
step the algorithm will be discussed. This algorithm can be easily coded into any
programming language. Further explanation of the algorithm is supported through an
example.
p(x)=anxn+an-1xn-1+…..+a1x1+a0x0
88
Consider a polynomial p(x) = ax2 + bx + c which can be written as x(x(a)+b)+c by
Analysis of simple Algorithms
using Horner‟s simplification.
Step I. Pseudo code for polynomial evaluation using Horner method, Horner(a,n,x)
//In this a is an array of n elements which are coefficient of polynomial of degree
n
1. Assign value of polynomial p= coefficient of nth term in the polynomial
2. set i= n-1
4. compute p = p * x + a[i];
5. i=i-1
6. if i is greater than or equal to 0 Go to step 4.
7. final polynomial value at x is p.
Step II. Algorithm to evaluate polynomial at a given point x using Horner‟s rule:
Evaluate_Horner(a,n,x)
{
p = a[n];
for (i = n-1; i 0;i--)
p = p * x + a[i];
return p;
}
At x=2,
p(x) = (x+3)x+2
p(2)=(2+3).2+2
= (5).2+2
=10+2
=12
Complexity Analysis
Every subsequent iteration uses the result of previous iteration i.e next iteration
multiplies the previous value of p then adds the next coefficient, i.e.
Thus, after n iterations, p = xn an + xn–1 an–1 + … + a0, which is the required correct
value.
89
Introduction to Algorithm
In above function
First step is one initial assignment that takes constant time i.e O(1).
For loop in the algorithm runs for n iterations, where each iteration cost O(1)
as it includes one multiplication, one addition and one assignment which takes
constant time.
Hence total time complexity of the algorithm will be O(n) for a polynomial of
degree n.
2. Write basic algorithm to evaluate a polynomial and find its complexity. Also
compare its complexity with complexity of Horner‟s algorithm.
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
Matrix is very important tool in expressing and discussing problems which arise
from real life cases. By managing the data in matrix form it will be easy to
manipulate and obtain more information. One of the basic operations on matrices is
multiplication.
In this section matrix multiplication problem is explained in two steps as we have
discussed GCD and Horner‟s Rule in previous section. In the first step we will brief
pseudo code and in the second step the algorithm for the matrix multiplication will be
discussed. This algorithm can be easily coded into any programming language.
Further explanation of the algorithm is supported through an example.
Let us define problem of matrix multiplication formally , Then we will discuss how to
multiply two square matrix of order n x n and find its time complexity. Multiply two
matrices A and B of order nxn each and store the result in matrix C of order nxn.
A square matrix of order nxn is an arrangement of set of elements in n rows and n
columns.
Let us take an example of a matrix of order 3 x 3 which is represented as
1. Multiply first row first element of first matrix with first column first element
of second matrix.
2. Similarly perform this multiplication for first row of first matrix and first
column of second matrix. Now take the sum of these values.
3. The sum obtained will be first element of product matrix C
4. Similarly Compute all remaining element of product matix C.
C= A x B
Step II : Algorithm for multiplying two square matrix of order n x n and find the
product matrix of order n x n
Matrix_Multiply(A,B,C,n)
{
A= 1 2 3
2 3 4
4 5 6
B= 1 1 1
2 3 2
3 2 1
= 14 13 8
20 19 12
32 31 20
91
Introduction to Algorithm
Complexity Analysis
First step is, for loop that will be executed n number of times i.e it will take O(n) time.
The second nested for loop will also run for n number of time and will take O(n) time.
Assignment statement inside second for loop will take constant time i.e O(1) as it
includes only one assignment.
The third for loop i.e innermost nested loop will also run for n number of times and
will take O(n ) time . Assignment statement inside third for loop will cost O(1) as it
includes one multiplication, one addition and one assignment which takes constant
time.
Hence, total time complexity of the algorithm will be O(n3) for matrix multiplication
of order nxn.
In section 3.4 of this unit we have discussed Horner‟s rule to evaluate polynomial
and its complexity analysis. But computing xn at some point x = a i.e an tends to brute
force multiplication of a by itself n times. So computing xn is most important
operation. It has many applications in various fields for example one of well known
field is cryptography and encryption methods. In this section we will discuss binary
exponentiation methods to compute xn . In this section first we will discuss pseudo
code then we will explain algorithm for computing xn . In this binary representation
of exponent n is used for computation of exponent. Processing of binary string for
exponent n to compute xn can be done by following methods:
left to right binary exponentiation
right to left binary exponentiation
In this method exponent n is represented in binary string. This will be processed from
left to right for exponent computation xn at x=a i.e an . First we will discuss its
pseudo code followed by algorithm.
1. Set result =a
2. set i=s-2
3. compute result = result * result
4. if A[i] = 1 then compute result = result * a
5. i=i-1 and if i is less than equal to 0 then go to step 4.
6. return computed value as result.
92
Step II : Algorithm to compute an by left to right binary exponentiation method is as
Analysis of simple Algorithms
follows:
1. result =a
2. for i=s-2 to 0
3. result = result * result
4. if A[i]= 1 then
5. result= result * a
6. return result (i.e an )
Iteration 1:
i=3
result=a *a= a2
A[3] 1
Iteration 2:
i=2
result= a2 * a2 = a4
A[2] 1
Iteration 3
i=1
result= a4 * a4 = a8
A[1] 1
Iteration 4
i=0
result= a8 * a8 = a16
A[0] = 1
result = a16 * a = a17
return a17
Hence
Total number of multiplications in the algorithm for computing an will be in the range
of s-1 ≤ f(n) ≤ 2(s-1) where s is length of the binary string equivalent to exponent n
and f is function that represent number of multiplication in terms of exponent n. So
93
complexity of the algorithm will sbe O(log2 n) As n can be representation in binary by
Introduction to Algorithm using maximum of s bits i.e n=2 which further implies s= O(log2 n)
In right to left binary exponentiation to compute an , processing of bits will start from
least significant bit to most significant bit.
1. Set x =a
2. if A[0]= 1 then set result =a
3. else set result =1
4. Initialize i=1
5. compute x = x * x
6. if A[i] = 1 then compute result = result * x
7. Increment i by 1 as i=i+1 and if i is less than equal to s-1 then go to step 4.
8. return computed value as result.
1. x=a
2. if A[0]=1 then
3. result = a
4. else
5. result=1
6. for i= 1 to s-1
7. x= x * x
8. if A[i]=1
9. result= result * x
10. return result (i.e an )
Step by step illustration of the right to left binary exponentiation algorithm for a17 :
s=5, the length of binary string of 1‟s and 0‟s for exponent n
Iteration 1:
i=1
x=a *a= a2
A[1] 1
Iteration 2:
i=2
x= a2 * a2 = a4
94
A[2] 1 Analysis of simple Algorithms
Iteration 3
i=3
x= a4 * a4 = a8
A[3] 1
Iteration 4
i=4
x= a8 * a8 = a16
A[4] = 1
result = result * x = a * a16 = a17
return a17
Total number of multiplications in the algorithm for computing an will be in the range
of s-1 ≤ f(n) ≤ 2(s-1) where s is length of the binary string equivalent to exponent n
and f is function that represent number of multiplication in terms of exponent n. So
complexity of the algorithm will be O(log2 n) As n can be representation in binary by
using maximum of s bits i.e n=2s which further implies s= O(log2 n)
From the above discussion we can conclude that the complexity for left to right
binary exponentiation and right to left binary exponentiation is logarithmic in terms
of exponent n.
3.6 SEARCHING
Computer system is generally used to store large amount of data. For accessing a data
item from a large data set based on some criteria/condition searching algorithms are
required. Many algorithms are available for searching a data item from large data set
stored in a computer viz. linear search, binary search. In this section we will discuss
the performance of linear search algorithm. Binary search will be discussed in the
Block-2. In the next section we will examine how long the linear search algorithm
will take to find a data item/key in the data set.
95
Introduction to Algorithm
3.7.1 Linear Search
We are given with a list of items. The following table shows a data set for linear
search:
7 17 3 9 25 18
In the above table of data set, start at the first item/element in the list and compared
with the key. If the key is not at the first position, then we move from the current item
to next item in the list sequentially until we either find what we are looking for or run
out of items i.e the whole list of items is exhausted. If we run out of items or the list is
exhausted, we can conclude that the item we were searching from the list is not
present.
In the given data set key 25 is compared with first element i.e 7 , they are not equal
then move to next element in the list and key is again compared with 17 , key 25 is not
equal to 17. Like this key is compared with element in the list till either element is
found in the list or not found till end of the list. In this case key element is found in the
list and search is successful.
Let us write the algorithm for the linear search process first and then analyze its
complexity.
function linear_search(a,n,key)
found=false // found is a boolean variable which will store either true or false
for(i=0;i<n;i++)
{
if (a[i]==key)
found = true
break;
}
if (i==n)
found = false
return found
}
For the complexity analysis of this algorithm, we will discuss the following cases:
Best Case:
The best case - we will find the key in the first place we look, at the beginning of the
list i.e the first comparison returns a match or return found as true. In this case we
only require a single comparison and complexity will be O(1).
Worst Case:
In worst case either we will find the key at the end of the list or we may not find the
key until the very last comparison i.e nth comparison. Since the search requires n
comparisons in the worst case, complexity will be O(n).
Average Case:
On average, we will find the key about halfway into the list; that is, we will compare
against n/2 data items. However, that as n gets larger, the coefficients, no matter what
they are, become insignificant in our approximation, so the complexity of the linear
search, is O(n). The average time depends on the probability that the key will be
found in the collection - this is something that we would not expect to know in the
majority of cases. Thus in this case, as in most others, estimation of the average time
is of little utility.
If the performance of the system is crucial, i.e. it's part of a life-critical system, and
then we must use the worst case in our design calculations and complexity analysis as
it tends to the best guaranteed performance.
3.7 SORTING
97
Introduction to Algorithm
Sorting techniques are broadly classified into two categories:
- Internal Sort: - Internal sorts are the sorting algorithms in which the complete
data set to be sorted is available in the computer‟s main memory.
- External Sort: - External sorting techniques are used when the collection of
complete data cannot reside in the main memory but must reside in secondary
storage for example on a disk.
In this section we will discuss only internal sorting algorithms. Some of the internal
sorting algorithms are bubble sort, insertion sort and selection sort. For any sorting
algorithm important factors that contribute to measure their efficiency are the size of
the data set and the method/operation to move the different elements around or
exchange the elements. So counting the number of comparisons and the number of
exchanges made by an algorithm provides useful performance measures. When
sorting large set of data, the number of exchanges made may be the principal
performance criterion, since exchanging two records will involve a lot of time. For
sorting a simple array of integers, the number of comparisons will be more important.
Let us discuss some of internal sorting algorithm and their complexity analysis in next
section.
In this we will discuss the bubble sort algorithm and study its complexity analysis.
A list of numbers is given as input that needs to be sorted. Let us explain the process
of sorting via bubble sort with the help of following Tables
23 18 15 37 8 11
18 23 15 37 8 11
18 15 23 37 8 11
18 15 23 37 8 11
18 15 23 8 37 11
18 15 23 8 11 37
18 15 23 8 11 37
15 18 23 8 11 37
15 18 23 8 11 37
15 18 8 23 11 37
15 18 8 11 23 37
15 18 8 11 23 37
15 18 8 11 23 37
15 8 18 11 23 37
15 8 11 18 23 37
15 8 11 18 23 37
8 15 11 18 23 37
8 11 15 18 23 37
8 11 15 18 23 37
8 11 15 18 23 37
8 11 15 18 23 37
In this the given list is divided into two sub list sorted and unsorted. The largest
element is bubbled from the unsorted list to the sorted sub list. After each
98
iteration/pass size of unsorted keep on decreasing and size of sorted sub list gets on
Analysis of simple Algorithms
increasing till all element of the list comes in the sorted list. With the list of n
elements, n-1 pass/iteration are required to sort. Let us discuss the result of iteration
shown in above tables.
In iteration 1, first and second element of the data set i.e 23 and 18 are compared and
as 23 is greater than 18 so they are swapped. Then second and third element will be
compared i.e 23 and 15 , again 23 is greater than 15 so swapped. Now 23 and 37 is
compared and 23 is less than 37 so no swapping take place. Then 37 and 8 is
compared and 37 is greater than 8 so swapping take place. At the end 37 is compared
with 11 and again swapped. As a result largest element of the given data set i.e 37 is
bubbled at the last position in the data set. Similarly we can perform other iterations
of bubble sort and after n-1 iteration we will get the sorted list.
int i,j,temp,flag=true;
{
flag=false
for(j=0; j<n-i-1; j++) // inner loop
{
if(a[j]>a[j+1])
{
flag=true
temp = a[j]; //
exchange a[j] = a[j+1]; //
exchange
a[j+1] = temp; // exchange
}
}
follows. Best-case:
When the given data set in an array is already sorted in ascending order the number of
moves/exchanges will be 0, then it will be clear that the array is already in order
because no two elements need to be swapped. In that case, the sort should end, which
takes O(1). The total number of key comparisons will be (n-1) so complexity in best
case will be O(n).
Worst-case:
99
Introduction to Algorithm
In this case the given data set will be in descending order that need to be sorted in
ascending order. Outer loop in the algorithm will be executed n-1 times (as i ranges
from 0 to n-2, when i will be n-1 it will exit from the loop).
Average –case:
In this case we have to consider all possible initial data arrangement. So as in case of
worst case, outer loop will be executed n-1 times. The number of exchanges will be
O(n2). The number of key comparison will be i.e O(n 2).So the complexity will be
O(n2).
This sort is usually applied by card players or for the insertion of new elements into a
sorted sequence. It is more appropriate for small input size of data/list. Let us consider
a data set to discuss the method of insertion sort as follows:
23 18 15 37 8 11
23 18 15 37 8 11
18 23 15 37 8 11
15 18 23 37 8 11
15 18 23 37 8 11
8 15 18 23 37 11
8 11 15 18 23 37
In insertion sort, the list will be divided into two parts sorted and unsorted. In each
pass, the first element of the unsorted part is picked up, transferred to the sorted sub
list, and inserted at the appropriate place. In each pass the algorithm inserts each
element of the array into its proper position. A list of n elements will take at most n-1
passes to sort the given data data in ascending order.
For the input data set under consideration, let us discuss iterations of insertion sort
algorithm. In first iteration first element of the list and second element of the list are
compared i.e 23 and 18. As 23 is greater than 18 , so they are exchanged. In second
iteration third element of the list i.e 15 is compared with second element and it is less
than that so second element 23 is shifted down then it is compared with first element
100
and it is less than that also so first element will also be shifted down. Now there is no
Analysis of simple Algorithms
more element above that so third element 15 appropriate position is first. This way
rest of the element will get their right position and sorted list will be obtained.
function insertionSort(a,n)
{
int i,j,key;
Running time depends not only on the size of the array but also the contents of the
array i.e already data is sorted or in descending order. Complexity analysis of
insertion sort algorithm is as follows.
Best-case:
In best case array data is already sorted in ascending order. Then inner loop will
not be executed at all and the number of moves/exchanges will be 2*(n-1) i.e O(n).
The number of key comparisons will be n-1 i.e O(n). So complexity in best case
will be O(n).
Worst case:
In worst case data element of the array will be given in descending order. In the outer
loop of above algorithm i range from 1 to n-1. So, the inner loop in the algorithm will
be executed n-1 times.
The number of key comparison will be (1+2+...+n-1)= n*(n-1)/2 i.e O(n2). Hence
complexity in worst case will be O(n2).
101
Introduction to Algorithm
Average case:
In this case we have to consider all possible initial data arrangement. It is difficult to
figure out the average case. i.e. what will be probability of data set either in mixed /
random input. We can not assume all possible inputs before hand and all cases will be
equally likely. For most algorithms average case is same as the worst case. So as in
case of worst case, outer loop will be executed n-1 times. The number of
moves/assignment will be O(n2). The number of key comparison will be i.e O(n2). So
the complexity in average case will be O(n2).
Now we will discuss the selection sort algorithm and its complexity analysis. A list of
numbers is given as input that needs to be sorted. Let us explain the process of
sorting via selection sort with the help of following Tables
23 18 15 37 8 11
8 18 15 37 23 11
8 11 15 37 23 18
8 11 15 37 23 18
8 11 15 37 23 18
8 11 15 18 23 37
8 11 15 18 23 37
In this algorithm the list will be divided into two sub lists, sorted and unsorted. Here
we find the smallest element of the list and replace it by the first element of the list i.e
beginning element of the given list. Then find the second smallest element and
exchange it with the element in the second position, and continue in this way until the
entire array is sorted. After each selection and swapping, the two sub lists will be
there where first sub list move one element ahead, increasing the number of sorted
elements and second sub list decreasing the number of unsorted elements by one. In
one pass we move one element from the unsorted sublist to the sorted sublist. A list of
n elements requires n-1 passes to completely rearrange the data in sorted i.e ascending
order.
For given data set, in first iteration minimum from the complete list is obtained i.e 8
so this will be exchanged with first position in the list i.e 23. Then in second iteration
minimum from the remaining list will be found out i.e 11 and exchanged with second
position element of the list i.e 18. This process will be continued for rest of the list
also and finally we will get sorted list.
In selectionsort function, the outer for loop executes n-1 times. Swap operation once
at each iteration of outer loop. Total number of Swaps will be n-1 and in each swap
operation three moves or assignment are performed. This gives the total
moves/assignment for outer loop as 3*(n-1). The inner loop executes the size of the
unsorted list minus 1 i.e from i+1 to n-1 for every iterations of outer loop. Number of
key comparison for each iteration of inner loop is one. Total number of key
comparisons will be equal to 1+2+...+n-1 = n*(n-1)/2 So, Selection sort complexity is
O(n2).
The following table will describe about number of moves and comparison.
Let us summarize the number of moves and comparison for selection sort algorithm.
The best case, the worst case, and the average case complexity of the selection sort
algorithm are same that is O(n2). As none of the loop in the algorithm is dependent on
the type of data either it is already sorted or in reverse order or mixed. It indicates that
behavior of the selection sort algorithm does not depend on the initial organization of
data.
103
Introduction to Algorithm
Following Table summarizes the above discussed results for different sorting
algorithms.
2. Write the iterations for sorting the following list of numbers using bubble
sort, selection sort and insertion sort:
45, 67, 12, 89, 1, 37, 25, 10
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
3.8 SUMMARY
In this unit various categories of algorithm and their analysis is described like GCD, matrix
multiplication, polynomial evaluation, searching and sorting. For GCD computation
Euclid‟s algorithm is explained and complexity in best case O(1) , worst case O(m) or
O(n) depending upon input and in average case it is O(log n). Horner‟s rule is
discussed to evaluate the polynomial and its complexity is O(n) where n will be the
degree of polynomial. Basic matrix multiplication is explain for finding product of
two matrices of order nxn with time complexity in the order of O(n3). For exponent
evaluation both approaches i.e left to right binary exponentiation and right to left
binary exponentiation is illustrated. Time complexity of these algorithms to compute
xn is O(log n). In large data set to access an element searching algorithm are
required. Here linear search algorithm and its analysis are discussed. Sorting is the
process of arranging a collection of data into either ascending or descending order.
Classification of sorting algorithm based on data storage in primary memory or secondary
memory. Internal sorting algorithms are applied where data to be sorted is stored in
primary memory. Otherwise if input data can not be stored in primary memory and
stored in secondary memory, external sorting techniques are used. In this unit few
internal sorting algorithms like bubble, selection and insertion and their complexity
analysis in worst case, best case and average are discussed.
104
Analysis of simple Algorithms
Answers:
1. 595 = 2 x 252 + 91
252 = 2 x 91 +70
91 = 1 x 70 + 21
70 = 3 x 21 + 7
21 = 3 x 7 + 0
GCD(595,252)= 7
Answers:
Iteration 1,
poly = x * 0 + a[4] = 3
Iteration 2,
poly = x * 3 + a[3]
= 2 * 3 + 2 = 6 +2 = 8
Iteration 3,
poly = x * 8 + a[2]
= 2 * 8 + 0 = 16 + 0 = 16
Iteration 4,
poly = x * 16 + a[1]
= 2 * 16 + (-5) = 32 -5 = 27
Iteration 5,
poly = x * 27 + a[0]
= 2 * 27 + 7 = 54 + 7 = 61
105
Introduction to Algorithm
2. A basic (general) algorithm:
function(a[n], n, x)
{
poly = 0;
Time Complexity of above basic algorithm is O(n2) where n is the degree of the
polynomial. Time complexity of the Horner‟s rule algorithm is O(n) for a polynomial
of degree n. Basic algorithm is inefficient algorithm in comparison to Horner‟s rule
method for evaluating a polynomial.
Answers:
#include<stdio.h>
int main()
{
int a[3][3],b[3][3],c[3][3],i,j,k,sum=0;
}
for(i=0;i<3;i++)
for(j=0;j<3;j++)
c[i][j]=0;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
sum=0;
for(k=0;k<3;k++)
sum=sum+a[i][k]*b[k][j]; c[i]
[j]=sum;
}
}
}
return 0;
}
Answers:
However, it is lengthy and time consuming where data set is large in size. There is no
quicker method to identify whether the item to be searched is present in the list or not.
The linear search situation will be in worst case if the element is at the end of the list.
In case of element is not present in the list then also whole list is required to be
searched.
2. List of numbers to be sorted 45, 67, 12, 89, 1, 37, 25, 10.
Bubble sort:
Iteration 1:
45,67,12,89,1,37,25,10
45,12,67,89,1,37,25,10
45,12,67,89,1,37,25,10
45,12,67,1,89,37,25,10
45,12,67,1,37,89,25,10
45,12,67,1,37,25,89,10
45,12,67,1,37,25,10,89
Iteration 2:
45,12,67,1,37,25,10
12,45,67,1,37,25,10
12,45,67,1,37,25,10
12,45,1,67,37,25,10
12,45,1,37,67,25,10
12,45,1,37,25,67,10
12,45,1,37,25,10,67
Iteration 3:
12,45,1,37,25,10
12,45,1,37,25,10
12,1,45,37,25,10
12,1,37,45,25,10
12,1,37,25,45,10
12,1,37,25,10,45
108
Iteration 4:
Analysis of simple Algorithms
12,1,37,25,10
1,12,37,25,10
1,12,37,25,10
1,12,25,37,10
1,12,25,10,37
Iteration 5:
1,12,25,10,
1,12,25,10,
1,12,25,10,
1,12,10,25
Iteration 6:
1,12,10,
1,12,10
1,10,12
Iteration 7:
1,10
1,10
Iteration 8:
Selection Sort:
45, 67, 12, 89, 1, 37, 25, 10
1,67,12,89,45,25,10
1,10,12,89,45,25,67
1,10,12,89,45,25,67
1,10,12,25,45,89,67
1,10,12,25,45,89,67
1,10,12,25,45,67,89
1,10,12,25,45,67,89
Insertion Sort:
45,67,12,89,1,37,25,10
12,45,67,89,1,37,25,10
12,45,67,89,1,37,25,10
1, 12,45,67,89,37,25,10
1,12,37,45,67,89,25,10
1,12,25,37,45,67,89,10
1,10,12, 25,37,45,67,89
109
Introduction to Algorithm
110
UNIT 1 GREEDY TECHNIQUES Greedy Techniques
Techniques
1.0 Introduction 5
1.1 Objectives 6
1.2 Some Examples to understand Greedy Techniques 6
1.3 Formalization of Greedy Techniques 9
1.4 Knapsack (fractional) problem 11
1.5 Minimum Cost Spanning Tree (MCST) problem 13
1.5.1 : Kruskal’s Algorithm
1.5.2 : Prim’s algorithm
1.6: Single-Source Shortest Path Problem 22
1.6.1 : Bellman-Ford algorithm
1.6.2 : Dijkstra’s Algorithm
1.7 Summary 35
1.8 Solutions/Answers 37
1.9 Further Readings 41
1.0 INTRODUCTION
5
Design Techniques Characteristics of greedy algorithm
In this unit, we will discuss those problems for which greedy algorithm
gives an optimal solution such as Knapsack problem, Minimum cost
spanning tree (MCST) problem and Single source shortest path problem.
1.1 OBJECTIVES
In order to better understand the greedy algorithms, let us consider some examples:
Suppose we are given Indian currency notes of all denominations, e.g.
{1,2,5,10,20,50,100,500,1000}. The problem is to find the minimum number of
currency notes to make the required amount A, for payment. Further, it is assumed
that currency notes of each denomination are available in sufficient numbers, so that
one may choose as many notes of the same denomination as are required for the
purpose of using the minimum number of notes to make the amount A.
Now in the following examples we will notice that for a problem (discussed above)
the greedy algorithm provides a solution (see example-1), some other cases, greedy
algorithm does not provides a solution, even when a solution by some other method
exist (see example-2) and sometimes greedy algorithm does not provides an optimal
solution Example-3).
Example 2
i) D ≤ 289 and
ii) if D1 is another denomination of a note such that D1 ≤ 289, then D1 ≤ D.
6
In other words, the picked-up note’s denomination D is the largest among all the Greedy Techniques
denominations satisfying condition (i) above.
To deliver Rs. 289 with minimum number of currency notes, the notes of different
denominations are chosen and rejected as shown below:
Example 2
Next, we consider an example in which for a given amount A and a set of available
denominations, the greedy algorithm does not provide a solution, even when a
solution by some other method exists.
Let us consider a hypothetical country in which notes available are of only the
denominations 20, 30 and 50. We are required to collect an amount of 90.
7
Design Techniques i) First, pick up a note of denomination 50, because 50 ≤ 90. The amount obtained
by adding denominations of all notes picked up so far is 50.
ii) Next, we can not pick up a note of denomination 50 again. However, if we pick
up another note of denomination 50, then the amount of the picked-up notes
becomes 100, which is greater than 90. Therefore, we do not pick up any note
of denomination 50 or above.
iii) Therefore, we pick up a note of next denomination, viz., of 30. The amount
made up by the sum of the denominations 50 and 30 is 80, which is less then
90. Therefore, we accept a note of denomination 30.
iv) Again, we can not pick up another note of denomination 30, because otherwise
the sum of denominations of picked up notes, becomes 80+30=110, which is
more than 90. Therefore, we do not pick up only note of denomination 30 or
above.
v) Next, we attempt to pick up a note of next denomination, viz., 20. But, in that
case the sum of the denomination of the picked up notes becomes
80+20=100, which is again greater than 90. Therefore, we do not pick up only
note of denomination 20 or above.
vi) Next, we attempt to pick up a note of still next lesser denomination. However,
there are no more lesser denominations available.
Thus, we get 90 and it can be easily seen that at least 3 notes are required to make an
amount of 90. Another alternative solution is to pick up 3 notes each of denomination
30.
Example 3
Next, we consider an example in which the greedy technique, of course, leads to a
solution, but the solution yielded by greedy technique is not optimal.
Again, we consider a hypothetical country in which notes available are of the only
denominations 10, 40 and 60. We are required to collect an amount of 80.
Using the greedy technique, to make an amount of 80, first, we use a note of
denomination 60. For the remaining amount of 20, we can choose note of only
denomination 10. And , finally, for the remaining amount, we choose another note of
denomination 10. Thus, greedy technique suggests the following solution using 3
notes: 80 = 60 + 10 + 10.
1) A candidate set from which a solution is created. It may be set of nodes, edges in
a graph etc. call this set as:
C: Set of given values or set of candidates
4) A selection function (say select) which chooses the best candidate form C to
be added to the solution set S,
To better understanding of all above mentioned data structure and functions, consider
the minimum number of notes problem of example1. In that problem:
2) Suppose we want to collect an amount of Rs. 283 (with minimum no. of notes). If
we allow a multi-set rather than set in the sense that values may be repeated, then
S={100,100,50,20,10,2,1}
4) A function select finds the “best” candidate value (say x) from C, then this value
x is tried to add to the set S. At any stage, value x is added to the set S, if its
addition leads to a partial (feasible) solution. Otherwise, x is rejected. For
example, In case of minimum number of notes problem, for collecting Rs. 283, at
the stage when S={100, 100,50}, then first the function select try to add the Rs 50
to S. But by using a function solution, we can found that the addition of Rs. 50 to
S will lead us a infeasible solution, since the total value now becomes 300 which
exceeds Rs. 283. So the value 50 is rejected. Next, the function select attempts the
next lower denomination 20. The value 20 is added to the set S, since after adding
20, total sum in S is 270, which is less than Rs. 283. Hence, the value 20 is
returned by the function select.
9
Design Techniques 5) When we select a new value (say x) using select function from set C, then before
adding x to S we check its feasibility. If its addition gives a partial solution, then
this value is added to S. Otherwise it is rejected. The feasibility checking of new
selected value is done by the function feasible. For example, In case of minimum
number of notes problem, for collecting Rs. 283, at the stage when S={100,
100,50}, then first the function select try to add the Rs 50 to S. But by using a
function solution, we can found that the addition of Rs. 50 to S will lead us an
infeasible solution, since the total value now becomes 300 which exceeds Rs.
283. So the value 50 is rejected. Next, the function select attempts the next lower
denomination 20. The value 20 is added to the set S, since after adding 20, total
sum in S is 270, which is less than Rs. 283. Hence feasible.
6) The objective function (say ObjF), gives the value of the solution. For example,
In case of minimum number of notes problem, for collecting Rs. 283; and when
S={100,100,50,20,10,2,1}, then the sum of values in S equals to the required
amount 283; the function ObjF returns the number of notes in S, i.e., the
number 7.
Algorithm Greedy(C, n)
/* Input: A input domain (or Candidate set ) C of size n, from which solution is to be
Obtained. */
}
If (solution (S))
return S;
else
return “ No Solution”
} // end of while
Now in the following sections, we apply greedy method to solve some optimization
problem such as knapsack (fractional) problem, Minimum Spanning tree and Single
source shortest path problem etc.
10
Greedy Techniques
1.4 KNAPSACK (FRACTIONAL) PROBLEM
The problem (or Objective) is to fill a knapsack (up to its maximum capacity M)
which maximizes the total profit earned.
Mathematically:
Note that the value of will be any value between 0 and 1 (inclusive). If any object
is completely placed into a knapsack then its value is 1 , if we do not pick
(or select) that object to fill into a knapsack then its value is 0 . Otherwise
if we take a fraction of any object then its value will be any value between 0 and 1.
To solve this problem, Greedy method may apply any one of the following strategies:
From the remaining objects, select the object with maximum profit that fit
into the knapsack.
From the remaining objects, select the object that has minimum weight and
also fits into knapsack.
From the remaining objects, select the object with maximum that fits
into the knapsack.
Approach
1
18+2+0=20 28.2
2
0+10+10=20 31.0
3
0+15+5=20 31.5
11
Design Techniques Approach 1: (selection of object in decreasing order of profit):
In this approach, we select those object first which has maximum profit, then next
maximum profit and so on. Thus we select 1st object (since its profit is 25, which is
maximum among all profits) first to fill into a knapsack, now after filling this object
( into knapsack remaining capacity is now 2 (i.e. 20-18=2). Next we select
nd
the 2 object, but its weight =15, so we take a fraction of this object
(i.e. = ). Now knapsack is full (i.e. ) so 3rd object is not selected.
Example: 1: Find an optimal solution for the knapsack instance n=7 and M=15 ,
Solution:
Greedy algorithm gives a optimal solution for knapsack problem if you select the
object in decreasing order of the ratio . That is we select those object first
which has maximum value of the ratio This ratio is also
called profit per unit weight .
Approach
Selection of
object in 6+10+18+15+3+3.33
decreasing 1+2+4+5+1+2 =55.33
order of the =15
ratio
10 10 10 10 10
a b 7 a b a b 7 a b 7 a b 7
12 9 e 12 e 12 e 12 11 e 9 e
c d 11 c d 11 c d c d c d
8 8 8 8 8
Figure-1 (a) (b) (c) (d)
A sum of the weights of the edges in and is: 41, 37, 38 and 34 (some
other spanning trees are also possible). We are interested to find that
spanning tree, out of all possible spanning trees , ……. ; whose sum
of weights of all its edges are minimum. For a given graph G is the MCST, since
weight of all its edges is minimum among all possible spanning trees of G.
1. Kruskal’s algorithm
2. Prim’s algorithm
These two algorithms use Greedy approach. A greedy algorithm selects the edges one-
by-one in some given order. The next edge to include is chosen according to some
optimization criteria. The simplest such criteria would be to choose an edge (u, v) that
results in a minimum increase in the sum of the costs (or weights) of the edges so for
included.
14
In General for constructing a MCST: Greedy Techniques
At each step, an edge (u, v) is determined such that A ∪ {(u, v)} is also a
Initially, A has no edges (i.e. empty set).
GENERIC_MCST(G, w)
{
}
return A
}
A main difference between kruskal’s and Prim’s algorithm to solve MCST problem
is that the order in which the edges are selected.
For solving MCST problem using Greedy algorithm, we use the following data
structure and functions, as mentioned earlier:
i) C: The set of candidates (or given values): Here C=E, the set of edges of
ii) S: Set of selected candidates (or input) which is used to give optimal
solution. Here the subset of edges, is a solution, if the graph
is a spanning tree of .
iii) In case of MCST problem, the function Solution checks whether a solution is
reached or not. This function basically checks :
a) All the edges in S form a tree.
b) The set of vertices of the edges in S equal to V.
c) The sum of the weights of the edges in S is minimum possible of the edges
which satisfy (a) and (b) above.
15
Design Techniques 1) ff selection function (say select) which chooses the best candidate form C
to be added to the solution set S,
iv) The select function chooses the best candidate from C. In case of Kruskal’s
algorithm, it selects an edge, whose length is smallest (from the remaining
candidates). But in case of Prim’s algorithm, it select a vertex, which is added
to the already selected vertices, to minimize the cost of the spanning tree.
v) A function feasible checks the feasibility of the newly selected candidate (i.e.
edge (u,v)). It checks whether a newly selected edge (u, v) form a cycle with
the earlier selected edges. If answer is “yes” then the edge (u,v) is rejected,
otherwise an edge (u,v) is added to the solution set S.
vi) Here the objective function ObjF gives the sum of the edge lengths in a
Solution.
Then we select an edge (u, v)∊ E of minimum weight and checks whether its end
First we examine the edges of G in order of increasing weight.
KRUSKAL_MCST(G, w)
/* Input: A undirected connected weighted graph G=(V,E).
/* Output: A minimum cost spanning tree T(V, E’) of G
{
1. Sort the edges of E in order of increasing weight
2.
3. for (each vertex )
16
In line 5-8: An edge (u, v)∊ E, of minimum weight is added to the set A, if Greedy Techniques
and only if it joins two nodes which belongs to different components (to
check this we use a function, which returns a same integer
value, if u and v belongs to same components (In this case adding (u,v) to A
creates a cycle), otherwise it returns a different integer value)
If an edge added to A then the two components containing its end points are
merged into a single component.
Finally the algorithm stops, when there is just a single component.
Let and
tree (MCST).
Solution: First, we sorts the edges of G=(V,E) in order of increasing weights as:
Edges
weights 2 3 4 4 5 5 5 6 7 8 8 9
2 3
1 2 3
6
5 7
5 8
4 9
4 5 6
8
5 4
7
17
Design Techniques
1. (1, 2) {1, 2},{3},{4},{5},{6},{7} (1) – (2) (3) (4) (5) (6) (7)
(4)–(5)
(4)–(5) (6)
(7)
5. (1, 4) {1,2,3,4,5},{6,7} (1)–(2)–(3)
(4)–(5) (6)
(7)
(4)–(5) (6)
(7)
18
1.5.2 Prim’s Algorithm Greedy Techniques
PRIM’s algorithm has the property that the edges in the set A (this set A contains the
edges of the minimum spanning tree, when algorithm proceed step-by step) always
form a single tree, i.e. at each step we have only one connected component.
edge (u, v) of minimum weight such that v∊ A and u∊ V-A. Then we modify
vertex v in the set A to the vertices in the set . That is, we always find an
This process is repeated until , i.e. until all the vertices are not in the set A.
PRIMS_MCST(G, w)
/* Input: A undirected connected weighted graph G=(V,E).
/* Output: A minimum cost spanning tree T(V, E’) of G
{
1. // T contains the edges of the MST
2.
3.
{
4. u∊ V-A and v∊ A
5.
6.
}
7. return T
}
1) Initially the set A of nodes contains a single arbitrary node (i.e. starting
vertex) and the set T of edges are empty.
2) At each step PRIM’s algorithm looks for the shortest possible edge such
that
u∊ V-A and v∊ A
3) In this way the edges in T form at any instance a minimal spanning tree for the
nodes in A. We repeat this process until .
2 3
1 2 3
7 6
5 5 8
4 9
4 5 6
8
5 4
7
(4)
(4)−(5)
(4)−(5)
(7)
6 (6,7) {1,2,3,4,5,6,7} (1)−(2)−(3)
(4)−(5) (6)
(7)
20
Check Your Progress 1 Greedy Techniques
Q2: The running time of KRUSKAL’s algorithm, where |E| is the number of edges
and |V| is the number of nodes in a graph:
a) O( E b) O( E log E c) O( E log V d) O(V log V )
) ) )
Q3: The running time of PRIM’s algorithm, where |E| is the number of edges and
|V| is the number of nodes in a graph:
O( E 2 O(V 2 c) O( E log V d) O(V log V )
) )
a) b) )
Q.4: The optimal solution to the knapsack instance n=3, M=15,
(P1 , P2 , (25,24,15) (W1 ,W2 ,W3 (18,15,10)
and is:
P3 ) )
a) 28.2 b) 31.0 c) 31.5 d) 41.5
Q.6: Total number of spanning tree in a complete graph with 5 nodes are
2 3
a) 5 b) 5 c) 10 d) 100
Q.7: Let
(i, j, C) , where i and j indicates vertices of a graph & C denotes cost
between edges. Consider the following edges & cost in order of increasing
length: (b,e,3),(a,c,4),(e,f,4), (b,c,5),(f,g,5),(a,b,6), (c,d,,6),(e,f,6), (b,d,7),
(d,e,7),(d,f,7),(c,f,7). Which of the following is NOT the sequence of edges
added to the minimum spanning tree using Kruskal’s algorithm?
Q.8: Consider a question given in Q.7. Applying Kruskal’s algorithm to find total cost
of a Minimum spanning tree.
Q.9: State whether the following Statements are TRUE or FALSE. Justify your
answer:
e) If edge weights of a connected weighted graph are not all distinct, the
minimum cost of each one minimum spanning tree is same.
Q.11: Differentiate between Kruskal’s and Prim’s algorithm to find a Minimum cost
of a spanning tree of a graph G..
Q.12: Are the Minimum spanning tree of any graph is unique? Apply PRIM’s
algorithm to find a minimum cost spanning tree for the following.
Graph following using Prim’s Algorithm. ( a is a starting vertex).
8 7
4 b c d 9
2
11 7 i 4 14 e
a
8 6 10
h g f
1 2
Q.13: Find the optimal solution to the knapsack instance n=5, M=10,
(P1, P2 ,...,P5 (12,32,40,30,50)
(W ,W ,......,
W
) (4,8,2,6,1) .
)
1 2 5
SSSP Problem can also be used to solve some other related problems:
All pair shortest path problem (APSPP): Find a shortest path between
every pair of vertices and . One technique is to use SSSP for each vertex,
but there are some more efficient algorithm (known as Floyed-warshall’s
algorithm).
1. Bellman-Ford algorithm
2. Dijkstra’s algorithm
Bellman-ford algorithm, allow negative weight edges in the input graph. This
algorithm either finds a shortest path from source vertex to every other
vertex or detect a negative weight cycles in G, hence no solution. If
there is no negative weight cycles are reachable (or exist) from source vertex
s, then we can find a shortest path form source vertex to every other
vertex . If there exist a negative weight cycles in the input graph, then
the algorithm can detect it, and hence “No solution”.
Dijkstra’s algorithm allows only positive weight edges in the input graph
and finds a shortest path from source vertex to every other vertex .
Case1: Shortest-path cannot contain a cycle; it is just a simple path (i.e. no repeated
vertex):
If some path from to contains a negative cost cycle, then there does not
exist a
shortest path. Otherwise there exists a shortest path (i.e. a simple path)
.
from
3 4
6
c d
5
S 0 5 11 -∞ g
-3
3
2 f 7
e
-∞ -∞
-6
There are infinitely many paths from s to c: 〈s, c〉, 〈s, c, d, c〉, 〈s, c, d, c, d, c〉
, and so on. Because the cycle 〈c, d, c〉 has weight 6 + (-3) = 3 > 0, the shortest path
from s to c is 〈s, c〉, with weight δ(s, c) = 5. Similarly, the shortest path from s to d is
〈s, c, d〉, with weight δ(s, d) = w(s, c) + w(c, d) = 11. Analogously, there are
infinitely many paths from s to e: 〈s, e〉, 〈s, e, f, e〉, 〈s, e, f, e, f, e〉, and so on. Since
the cycle 〈e, f, e〉 has weight 3 + (-6) = -3 < 0, however, there is no shortest path
from s to e. By traversing the negative-weight cycle 〈e, f, e〉 arbitrarily many times,
we can find paths from s to e with arbitrarily large negative weights, and so δ(s, e) = -
∞. Similarly, δ(s, f) = -∞. Because g is reachable from f , we can also find paths with
arbitrarily large negative weights from s to g, and δ(s, g) = -∞. Vertices h, i, and j also
form a negative-weight cycle. They are not reachable from s, however, and so δ(s, h)
= δ(s, i) = δ(s, j) = ∞.
Some shortest-paths algorithms, such as Dijkstra's algorithm, assume that all edge
weights in the input graph are non negative, as in the road-map example. Others,
such as the Bellman-Ford algorithm, allow negative-weight edges in the input graph
and produce a correct answer as long as no negative-weight cycles are reachable
from the source. Typically, if there is such a negative-weight cycle, the algorithm can
detect and report its existence.
P2
24
Greedy Techniques
v w
Negative weight cycles are not allowed when it is reachable from source vertex s,
since in this case there is no shortest path.
If Positive –weight cycles are there then by removing the cycle, we can get a
shorter path.
2. The
value of is either a another vertex or NIL
Initialization:
INITIALIZE_SIGLE_SOURCE(V,s)
1.
2. do
3.
4.
Relaxing an edge :
The SSSP algorithms are based on the technique known as edge relaxation. The
process of relaxing an edge consists of testing whether we can improve (or
reduce) the shortest path to found so far (i.e by going through and taking
and, if so, update and This is accomplished by the following
procedure:
25
Design Techniques
RELAX(u,v,w)
1.
2. then
3.
u v u v
5 2 2
9 5 6
2 2
5 7 5 6
Note:
In Dijkstra’s algorithm and the other shortest-path algorithm for directed acyclic
graph, each edge is relaxed exactly once. In a Bellman-Ford algorithm, each edge
is relaxed several times
C<O
26
Greedy Techniques
BELLMAN_FORD(G,w,s)
1. INITIALIZE_SIGLE_SOURCE(G,s)
2.
3.
4. do
5.
6. do
7. then // we detect a negative weight cycle
exist
7.
2. For loop at line-2 executed times which Relaxes all the E edges, so
line 2-4 requires .
3. For loop at line 5 checks negative weight cycle for all the E edges,
which requires O(E) time.
27
Design Techniques Order of edge: (B,E), (D,B), (B,D), (A,C), (D,C), (B,C), (E,D)
B
2
-1 2
3 1 A B C D E
0
0 A E
4 C D -3
5
B
2
-1 2 A B C D E
3 1
0
0 A E 0 -1
4 C D -3
5
A B C D E
B 0
-1
2 0 -1
2
3 1 0 -1 4
0 A E
4 C D -3
5
A B C D E
0
0 -1
0 -1 4
0 -1 2
B
2
-1
2
3 1
A B C D E
0 A E
-3 1 0
4 C D
5 0 -1
0 -1 4
0 -1 2
0 -1 2 1
28
Greedy Techniques
A B C D E
B 0
0 -1
0 -1 4
2
-1 2
0 -1 2
3 1
01 -1 2
0 A E
-3 1
0 -1 2 1
4 C D
5
1
A B C D E
B
0
2 0 -1
0 -1 4
-1
2
3
0 -1 2
1
0 -1 2
0 A E
-3 1
0 -1 2 1
4 C
5
D 1
0 -1 2 -2
1
1
A B C D E
B
0
-1 2 0 -1
2
3 1 0 -1 4
0 A E
0 -1 2
-3 1
4 C
5
D 0 -1 2 1
0 -1 2 1 1
0 -1 2 -2 1
Dijkstra’s algorithm, named after its discoverer, Dutch computer scientist Edsger
Dijkstra, is a greedy algorithm that solves the single-source shortest path problem for
a directed graph G=(V,E) with non-negative edge weights i.e. we assume that w
(u,v)
≥ 0 for each edge (u, v) ∈ E.
DIJKSTRA(G, w, s)
29
Design Techniques 1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S←Ø
3 Q ← V[G]
4 while Q ≠ Ø
S ← S ∪{u}
5 do u ← EXTRACT-MIN(Q)
Because Dijkstra’s algorithm always choose the “lightest” or “closest” vertex in V-S
to insert into set S, we say that it uses a greedy strategy.
Dijkstra’s algorithm bears some similarly to both breadth-first search and Prim’s
algorithm for computing minimum spanning trees. It is like breadth-first search in
that set S corresponds to the set of black vertices in a breadth-first search; just as
vertices in S have their final shortest-path weights, so do black vertices in a breadth-
first search have their correct breadth- first distances.
Dijkstra’s algorithm is like prim’s algorithm in that both algorithms use a min-priority
queue to find the “lightest” vertex outside a given set (the set S in Dijkstra’s algorithm
and the tree being grown in prim’s algorithm), add this vertex into the set, and adjust
the weights of the remaining vertices outside the set accordingly.
The running time of Dijkstra’s algorithm on a graph with edges E and vertices V can
be expressed as function of |E| and |V| using the Big-O notation. The simplest
implementation of the Dijkstra’s algorithm stores vertices of set Q an ordinary linked
list or array, and operation Extract-Min (Q) is simply a linear search through all
vertices in Q.
For sparse graphs, that is, graphs with many fewer than |V|2 edges, Dijkstra’s
algorithm can be implemented more efficiently, storing the graph in the form of
adjacency lists and using a binary heap or Fibonacci heap as a priority queue to
implement the Extract-Min function. With a binary heap, the algorithm requires O((|E|
+ |V|) time (which is dominated by O|E|log|V|) assuming every vertex is connected,
and the Fibonacci heap improves this to O|E| + |V|log|V|).
Example1:
Apply Dijkstra’s algorithm to find shortest path from source vertex A to each of the
other vertices of the following directed graph.
2
B D
10
8 7 9
A 1 4
3
C 2 E
Solution:
30
vertex u ∈V-S with the minimum shortest-path estimate, inserts u into S and relaxes Greedy Techniques
all edges leaving u. We maintain a min-priority queue Q that contains all the vertices
in keyed by their d values.
Initialize:
2 Q: A B C D E
B D
10 0
0 8 7 9
A 1 4
3
C 2 E
S={}
“A” ← EXTRACT-MIN(Q)
2
B D Q: A B C D E
10
0
8 9
0 A 1 4 7
10
Q:
3
C 2 E
A B C D E
2 0
B D 10 3 - -
10
8 7 9
0 A 1 4
3
C 2 E
3
S:{A}
“C” ← EXTRACT-MIN(Q)
10
2 Q: A B C D E
B D
10 0
10 3 - -
8 9
0 A 1 4 7
3
C 2 E
3
S:{A,C}
31
Design Techniques
Relax all edges leaving C:
7 11
Q: A 2 B C D E
B D
10 0
10 3
8
0 A 1 4 7 7 19 1 5
3
C 2 E
3 5
S:{A,C}
“E”← EXTRAXT-MIN(Q)
7 11
2
B D Q: A B C D E
10
0
8 7 9
10 3 - -
0 A 1 4
7 11 5
3
C 2 E
3 5
S:{A,C,E}
7 11
B
2
D
Q: A B C D E
10 0
10 3
8 7 9
0 A 1 4 7 11 5
7 11
3
C 2 E
3 5
S:{A,C,E}
“B” ← EXTRACT-MIN(Q):
7
2 11
B Q: A B C D E
10 D
0
0 A 1 4
8
7 9
10 3
7 11 5
3 7 11
C 2 E
3 5
S:{A,C,E,B}
32
Greedy Techniques
Relax all edges leaving B:
7 9
2 Q: A B C D E
B D
10 0
10 3
8 7 11 5
0 A 1 4 7 9
7 11
3 9
C 2 E
3
5
S:{A,C,E,B}
“D” ←EXTRACT-MIN(Q):
7
2 9
B
D Q: A B C D E
10
0
0
8 10 3
A 1 4 7 9
7 11 5
3 7 11
C 2 9
E
3
5
S:{A,C,E,B,D}
source
10 d = 10
1 6
2 20
10
1 6
2 20 2 6 5
9 d = 20
d=2
6
2 5
2 d= 3 4 d=6
10 12
3 4
4 (initial) S={1}
S={ }
10
10 1 6 d=10
1 6 d=10 2
20
2 20
d=2 2 5 d=18
d=2 2 6
6 5 d=20
10
10 12
d=10 3 4 d=6
d=12 3 4 d=6
4
(2) S={1, 2, 4}
(1) S= {1, 2}
33
Design
Techniques 10
1 6 d=10
2
10 9
1 6 d=10
2 d=2 2 6
5 d=12
20
d=2 6 2
2 5 d=12 12
2 d=10 3 4 d=6
4
12
d=10 3 (4) S= {1, 2, 4, 3, 6}
4 d=6
4
(3) S= {1, 2, 4, 3}
10
5 5 d=10
2
6
d=2 5 5 d=12
2
12
d=10 5 5 d=6
4
(5) S={1, 2, 4, 3, 6, 5}
Initi {} 0 ∞ ∞ ∞ ∞ ∞ 1
al 1 (1} [0] 2 ∞ 6 20 10 2
2 {1,2} [2] 12 6 20 10 4
3 (1,2,4} 10 [6] 18 10 3
4 {1,2,4,3} [10] 18 10 6
5 {1,2,4,3,6} 12 [10] 5
{1,2,4,3,6,5} [12]
34
Greedy Techniques
Q.1: Dijkstra’s algorithm running time, where n is the number of nodes in a graph is:
a) O(n 2 b) O(n3 ) c) O(n) d) O(n log n)
)
Q2: This of the following algorithm allows negative edge weight in a graph to find
shortest path?
Q.4: Consider a weighted undirected graph with positive edge weights and let
(u, v) be
an edge in the graph. It is known that the shortest path from source vertex s to u
has weight 60 and the shortest path from source vertex s to v has weight 75. which
statement is always true?
a) weight
(u, v) 15 (u, 15 c) weight (u, v) 15 d) weight
b) weight
v)
(u, v) 15
Q.5: Which data structure is used to maintained the distance of each node in a
Dijkstras’s algorithm.
a) Stack b) Queue c) Priority Queue d) Tree
Q.7: Find the minimum distance of each station from New York (NY) using
Dijkstra’s algorithm. Show all the steps.
Boston
1 LA
10 2 4
NY 1 2 3 9 4 6
5 7
3 5
CK 2 WN
1.7 SUMMARY
Generally an optimization problem has n inputs (call this set as input domain or
Candidate set, C), we are required to obtain a subset of C (call it solution set, S
where S ) that satisfies the given constraints or conditions. Any subset S ,
which satisfies the given constraints, is called a feasible solution. We need to find
a feasible solution that maximizes or minimizes a given objective function. The
feasible solution that does this is called a optimal solution.
Greedy algorithm always makes the choice that looks best at the moment. That is,
it makes a locally optimal choice in the hope that this choice will lead to a
overall globally optimal solution.
Greedy algorithm does not always yield an optimal solution; but for many
problems they do.
The (fractional) Knapsack problem is to fill a knapsack or bag (up to its maximum
capacity M) with the given which maximizes the total profit earned.
There are two algorithm to find a MCST of a given directed graph G, namely
Kruskal’s algorithm and Prim’s algorithm.
The basic difference between Kruskal’s and Prim’s algorithm is that in kruskal’s
algorithm it is not necessary to choose adjacent vertices of already selected
vertices (in any successive steps). Thus At intermediate step of algorithm, there
are may be more than one connected components of trees are possible. But in case
of Prim’s algorithm it is necessary to select an adjacent vertex of already selected
vertices (in any successive steps). Thus at intermediate step of algorithm, there
will be only one connected components are possible.
1.8 SOLUTIONS/ANSWERS
Solution 8:
3
b e
2
5 d 4 e
a
4 6 5
c f
Solution 9:
(a) FALSE, since edge with the smallest weight will be part of every minimum
spanning tree.
(b) TRUE: edge with the smallest weight will be part of every minimum
spanning tree.
(c) TRUE:
(d) TRUE: Since more than one edges in a Graph may have the same weight.
(e) TRUE: In a connected weighted graph in which edge weights are not all distinct,
then the graph must have more than one spanning tree but the minimum cost of
those spanning tree will be same.
Solution 10:
Algorithm Greedy(C, n)
/* Input: A input domain (or Candidate set ) C of size n, from which solution is to be
Obtained. */
// function select (C: candidate_set) return an element (or candidate).
// function solution (S: candidate_set) return Boolean
// function feasible (S: candidate_set) return Boolean
/* Output: A solution set S, where S , which maximize or minimize the selection
criteria w. r. t. given constraints */
{
}
If (solution (S))
return S;
else
return “ No Solution”
} // end of while
Solution11:
A main difference between kruskal’s and Prim’s algorithm to solve MCST problem
is that the order in which the edges are selected.
8 7
b c d
4 9
2
i 5 e
a
h g f
1 2
Solution 13:
Thus the item which has maximum value will be placed into a knapsack first,
That is 5th item first, then 3rd item then 4th item then 2nd and then 1st item (if capacity
of knapsack is remaining). The following table shows a solution of this knapsack
problem.
S.No Solution Set
1
158
Solution 14:
The item which has maximum value will be placed into a knapsack first. Thus
the sequence of items placed into a knapsack is: 6th , 5th ,1st ,2nd, 3rd , 4th and then 7th
item. The following table shows a solution of this knapsack problem.
S.No Solution Set
1
49.4
39
Design Techniques Check Your Progress 2
Solution 6:
Bellman-ford algorithm, allow negative weight edges in the input graph. This
algorithm either finds a shortest path from source vertex to every other
vertex or detect a negative weight cycles in G, hence no solution. If
there is no negative weight cycles are reachable (or exist) from source vertex
s, then we can find a shortest path form source vertex to every other
vertex . If there exist a negative weight cycles in the input graph, then
the algorithm can detect it, and hence “No solution”.
Dijkstra’s algorithm allows only positive weight edges in the input graph
and finds a shortest path from source vertex to every other vertex .
Solution 7:
Following Table summarizes the Computation of Dijkstra’s algorithm for the given
digraph of Question 7.
Initial {} 0 ∞ ∞ ∞ ∞ 1
1 (1} [0] 10 5 ∞ ∞ 3
2 {1,3} 8 [5] 14 7 2
3 (1,3,2} [8] 14 7 5
4 {1,3,2,5} 13 [7] 4
5 {1,3,2,5,4) [13]
Solution 8: The running time of Dijkstra’s algorithm on a graph with edges E and
vertices V can be expressed as function of |E| and |V| using the Big-O notation. The
simplest implementation of the Dijkstra’s algorithm stores vertices of set Q an
ordinary linked list or array, and operation Extract-Min (Q) is simply a linear search
through all vertices in Q. in this case, the running time is O(|V|2 + |E| )= O(V2).
40
Greedy Techniques
3.9 FURTHER READING
1. Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson (PHI)
2. Foundations of Algorithms, R. Neapolitan & K. Naimipour: (D.C. Health &
Company, 1996).
3. Algoritmics: The Spirit of Computing, D. Harel: (Addison-Wesley Publishing
Company, 1987).
4. Fundamentals of Algorithmics, G. Brassard & P. Brately: (Prentice-Hall
International, 1996).
5. Fundamental Algorithms (Second Edition), D.E. Knuth: (Narosa Publishing
House).
6. Fundamentals of Computer Algorithms, E. Horowitz & S. Sahni: (Galgotia
Publications).
7. The Design and Analysis of Algorithms, Anany Levitin: (Pearson Education,
2003).
8. Programming Languages (Second Edition) ─ Concepts and Constructs, Ravi
Sethi: (Pearson Education, Asia, 1996).
41
UNIT 2 DIVIDE AND CONQUER APPROACH
Structure Page Nos.
2.0 Introduction 42
2.1 Objective 42
2.2 General Issues in Divide and Conquer 43
2.3 Binary Search 45
2.4 Sorting 49
2.4.1: Merge sort
2.4.2 : Quick sort
2.5 Integer multiplication 67
2.6 Matrix multiplication 70
2.7 Summary 75
2.8 Solution/Answers 76
2.9 Further Readings 81
2.0 INTRODUCTION
We have already mentioned in unit-1 of Block-1 that there are five fundamental
techniques which are used to design the Algorithm efficiently. These are: Divide and
Conquer, Greedy Method, Dynamic Programming, Backtracking and Branch and
Bound. Out of these techniques Divide & Conquer is probably the most well-known.
Many useful algorithms are recursive in nature. To solve a given problem, they call
themselves recursively one or more times. These algorithms typically follow a divide
& Conquer approach. A divide & Conquer method works by recursively breaking
down a problem into two or more sub-problems of the same type, until these become
simple enough (i.e. smaller in size w.r.t. original problem) to be solved directly. The
solutions to the sub-problems are then combined to give a solution to the original
problem.
Subsolutions-1
Sub-problem 1
Subsolutions-2
Any problem (such Sub-problem 2 Solution
as Quick sort,
Merge sort, etc.)
Subsolutions-n
Sub-problem n
Thus, in general, a divide and Conquer technique involves 3 Steps at each level of
recursion:
42
Step 1: Divide the given big problem into a number of sub-problems that are similar
to the original problem but smaller in size. A sub-problem may be further Divide and Conquer
Approach
divided into its sub-problems. A Boundary stage arrives when either a direct
solution of a sub-problem at some stage is available or it is not further sub-
divided. When no further sub-division is possible, we have a direct solution
for the sub-problem.
In this unit we will solve the problems such as Binary Search, Searching - QuickSort,
MergeSort, integer multiplication etc by using Divide and Conquer method;
2.1 OBJECTIVES
Thus any algorithms which follow the divide-and-conquer strategy have the following
recurrence form:
43
Design Techniques Where
If the problem size is small enough (say, n ≤ c for some constant c), we have a
base case. The brute-force (or direct) solution takes constant time: Θ(1)
Otherwise, suppose that we divide into a sub-problems, each 1/b of the size of
the original problem of size n.
Suppose each sub-problem of size n/b takes time to solve and since
there are a sub-problems so we spend total time to solve sub-
problems.
is the cost(or time) of dividing the problem of size n.
is the cost (or time) to combine the sub-solutions.
Thus in general, an algorithm which follow the divide and conquer strategy have the
following recurrence:
Where
T(n) = running time of a problem of size n
a means “In how many part the problem is divided”
means “Time required to solve a sub-problem each of size (n/b)”
D(n) + C(n) = f(n) is the summation of the time requires to divide the
problem and combine the sub-solutions.
MERGE_SORT (A, p, r)
1. if (p < r)
2. then q ← *(p + r)/2] /* Divide
3. MERGE_SORT (A, r, q) /* Conquer
4. MERGE_SORT (A, q + 1, r) /* Conquer
5. MERGE (A, p, q, r) /* Combine
To set up a recurrence T(n) for MERGE SORT algorithm, we can note down the
following points:
Base Case: MERGE SORT on just one element (n=1) takes constant time i.e.
44
When we have n > 1 elements, we can find a running time as follows: Divide and Conquer
Approach
(1) Divide: Just compute q as the middle of p and r, which takes
constant time. Thus
(2) Conquer: We recursively solve two sub-problems, each of size n/2, which
contributes
(3) Combine: Merging two sorted subarrays (for which we use MERGE (A,
p, r) of an n-element array) takes time , so .
Thus , which is a linear
function of n.
Thus from all the above 3 steps, a recurrence relation for MERGE_SORT (A, 1, n) in
the worst case can be written as:
Now after solving this recurrence by using any method such as Recursion-tree or
Master Method (as given in UNIT-1), we have .
This algorithms will be explained in detailed in section 2.4.2
Search is the process of finding the position (or location) of a given element (say x) in
the linear array. The search is said to be successful if the given element is found in
the array otherwise it is considered unsuccessful.
(1) Begin with the interval covering the whole array; binary search repeatedly
divides the search interval by half.
(2) At each step, the algorithm compares the input key (or search) value x with the
key value of the middle element of the array A.
(3) If it matches, then a searching element x has been found, so then its index, or
position, is returned. Otherwise, if the value of the search element x is less than
the item in the middle of the interval; then the algorithm repeats its action on the
sub- array to the left of the middle element or, if the search element x is greater
than the middle element‘s key, then on the sub-array to the right.
45
Design Techniques (4) We repeatedly check until the searched element is found or the interval is
empty, which indicates x is ―not found‖.
BinarySearch_Iterative(A[1…n],n,x)
Output: This algorithm find the location of the search element x in linear array A. If
search ends in success, it returns the index of the searched element x, otherwise returns
-1 indicating x is “not found”. Here variable low and high is used to keep track of the
first element and last element of the array to be searched, and variable mid is used as
index of the middle element of the array under consideration. */
{
low=1
high=n
while(low<=high)
{
mid= (low+high)/2
if(A[mid]==x]
return mid; // x is found
else if(x<A[mid])
high=mid-1;
else low=mid+1;
}
return -1 // x is not found
}
Method1:
Let us assume for the moment that the size of the array is a power of 2, say . Each
time in the while loop, when we examine the middle element, we cut the size of the
sub-array into half. So before the 1st iteration size of the array is 2k.
After the 1st iteration size of the sub-array of our interest is: 2k-1
After the 2nd iteration size of the sub-array of our interest is:
……
…….
After the .iteration size of the sub-array of our interest is :
So we stop after the next iteration. Thus we have at most
.iterations.
Since with each iteration, we perform a constant amount of work: Computing a mid
point and few comparisons. So overall, for an array of size n, we perform
comparisions. Thus
Method 2:
46
We know that any problem, which is solved by using Divide-and-Conquer having a
Divide and Conquer
Approach
recurrence of the form:
Since at each iteration, the array is divided into two sub-arrays but we are solving only
one sub-array in the next iteration. So value of a=1 and b=2 and f(n)=k where k is a
constant less than n.
Thus a recurrence for a binary search can be written as
11 22 30 33 40 44 55 60 66 77 80 88 99
Illustrate the working of binary search technique, while searching an element (say
ITEM)
(i) 40 (ii) 85
Solution
(a) Suppose ITEM = 40. The search for ITEM in the array DATA is pictured
in Fig.1, where the values of DATA[Low] and DATA[High] in each
stage of the algorithm are indicated by circles and the value of
DATA[MID] by a square. Specifically, Low, High and MID will have the
following successive values:
2. Since 40 < 55, High has its value changed by High = MID – 1 =
6. Hence MID = so DATA
3. Since 40 < 30, Low has its value changed by Low = MID – 1 = 4.
Hence MID = so DATA
47
Design Techniques
We have found ITEM in location LOC = MID = 5.
(1) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99,
(2) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
(3) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99 [Successful]
(b) Suppose ITEM = 85. The binary search for ITEM is pictured in Figure
2. Here Low, High and MID will have the following successive values:
2. Since 85 > 55, Low has its value changed by Low = MID + 1 = 8. Hence
MID = so DATA
3. Since 85 > 77, Low has its value changed by Low = MID + 1 = 11. Hence
MID = so DATA
4. Since 85 > 88, High has its value changed by High = MID – 1 = 11.
Hence
MID = so
DATA
Since 85 > 80, Low has its value changed by Low = MID + 1 = 12. But now
Low > High, Hence ITEM does not belong to DATA.
(1) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99,
(2) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
(3) 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80 88, 99 [unsuccessful]
48
Using the binary search algorithm, one requires only about 20 comparisons to find
Divide and Conquer
the location of an ITEM in an array DATA with elements, since
Approach
7 14 17 25 30 48 56 75 87 94 98 115 200
Illustrate the working of binary search algorithm, while searching for ITEM
(i) 17 (ii) 118
6. Analyze the running time of binary search algorithm in best average and
worst cases.
2.4 SORTING
Sorting is the process of arranging the given array of elements in either increasing or
decreasing order.
2.4.1 MERGE-SORT
Merge Sort algorithm closely follows the Divide-and-conquer strategy. Merge sort on
an input array A [1… n] with n-elements (n > 1) consists of (3) Steps:
49
Design Techniques
Divide: Divide the n-element sequence into two sequences of length n/2 and n/2
(say A1 = A(1), (2), …..A[ n/2 ] and A2 A[ n/2 +1], ….A[n])
Conquer: Sort these two subsequences A1 and A2 recursively using MERGE SORT;
and then
Combine: Merge the two sorted subsequences A1 and A2 to produce a single sorted
subsequence.
n
Divide Array A into two halves of size
A *1+, A*2+......................, Av*n+ n/2 and n/2
Sorted
Where Array
is a …operator and
Is a floor operator
Merge
Recursively Sort A1
A*1+, A*2+, ……..A* n/2 ] A[ n/2 +1+, ….., A*n+
and A2 using MERGE-
Sorted Array SORT
(A1) (A2)
Figure 6: Illustrate the operation of two- way merge sort algorithm. We assume to
sort the given array A [1…n] into ascending order. We divide the given array A [1..n]
into 2 subarrays: A[1, … n/2 ] and [ n/2 +1, …. n]. Each subarray is individually
sorted, and the resulting sorted subarrays are merged to produce a single sorted array
of n- elements.
For example, consider an array of 9 elements :{ 80, 45 15, 95, 55, 98, 60, 20, 70}
The MERGE-SORT algorithm divides the array into subarrays and merges them
into sorted subarrays by MERGE () algorithm as illustrated in arrows the (dashed
line arrows indicate the process of splitting and regular arrows the merging process).
50
Divide and Conquer
[1] [2] [3] [4] [5] [6] [7] [8] [9] Approach
80 45 15 95 55 98 60 20 70
divide
merge
[1] [2] [6] [7] [8] [9]
45 80 20 60 70 98
1st, left half of the array with 5-elements is being split and merge; and next
second half of the array with 4-elements is processed.
Since, here we are always dealing with sub-problems, we state each sub-problem as
sorting a subarray A [p…r]. Initially p = 1 and r = n, but these values changes as
we recurse through sub-problems.
51
Design Techniques Thus, to sort the subarray A[p…r]
1) Divide: Partition A [p…r] into two subarrays A [p…q] and A [q+1…r], where q is
the half way point of A [p…r].
3) Combine: Merge the two sorted subarray A [p..q] and A[q+1..r] to produce a
single sorted subarray A[p..r]. To accomplish this step, we will define a procedure
MERGE (A, p, q, r).
Note that the recursion stops, when the subarray has just 1 element, so that it is
trivially sorted.
Algorithm:
{
1. if (p < r) /* Check for base case
{
2. q ← (p + r)/2 /* Divide step
3. Merge-Sort (A,p,q) /* Conquer step
4. MERGE-SORT (A,q+1,r) /* Conquer step
5. MERGE (A,p,q,r) /* Combine step
}
}
Next, we define Merge (A, p, q, r), which is called by the Algorithm MERGE-SORT
(A, p, q).
Merging
Output: The two subarrays are merged into a single sorted subarray in A [p..r]
52
Divide and Conquer
Approach
The following Algorithm merge the two sorted subarray A [p.. r] and A [q+1..r] into
one sorted output subarray A [p..r].
Merge (A, p, q, r)
1. n1 ← q – p + 1 // No. of elements in sorted subarray A [p..q]
2. n2 ← r – q // No. of elements in sorted subarray A[q+1 .. r]
Create arrays L [1.. n1 +1] and R [1..n1 +1]
3. for i ← 1 to n1
4. do L[i] ← A [p + I -1] // copy all the elements of A [p..r] into L [1 .. n1]
5. for j ← 1 to n1
6. do R [j] ← A [q + j] // copy all the elements of A [q + 1, .. r] into
R[1..n2]
7. L [n1 +1] ← ∞
8. R [n2 + 1] ← ∞
9. i ← 1
10. j ← 1
11. for k ← p to r
12. do if L [i] ≤ R [j]
13. then A [k] ← L [i]
14. i ← i +1
15. else A [k] ← R [j]
16. j←j+1
53
Design Techniques To understand both the algorithm Merge-Sort (A, p, r) and MERGE (A, p, q,
r); consider a list of (7) elements:
1 2 3 4 5 6 7
A 70 20 30 40 10 50 60
p q r
1 2 3 4 5 6 7
70 20 30 40 10 50 60
p q q+1 r
(1) This sub array is (4) this array
further sub-divided can be
subdivided as
1 2
70 20 30 40 10 50 60
(2)This subarray (3) This subarray (5) Again
is a again divided can be subdivided
subdivided
1 2 3 4 5 6
70 20 30 40 10 50
(6)Combine two (7) combine back
sorted subaaray to original array
back to original A[p..r]
(9)combine
array A[p…r]
1 2 \3 4 5 6
20 70 30 40 10 50
(10)
merge
20 30 40 50 60 10 50 60
(11)combine these
two sorted subarray
1 2 3 4 5 6 7
10 20 30 40 50 60 70
Figure 10: Illustration of merging process - 1
54
Lets us see the MERGE operation more closely with the help of some example.
Consider that at some instance we have got two sorted subarray in A, which we have Divide and Conquer
Approach
to merge in one sorted subarray.
Ex: 1 2 3 4 5 6 7
A 20 30 40 70 10 50 60
1 2 3 4 5 6 7
A 20 30 40 70 10 50 60
k
1 2 3 4 5 1 2 3 4
L 20 30 40 70 R 10 50 60
i J
In figure (a), we just copy the A[p…q] into L[1..n1] and A[q+1,…r] into R[1…n2]
Variable I and j both are pointing to 1st element of an array L & R, respectively.
Now line 11-16 of MERGE (A,p,q,r) is used to merge the two sorted subarray
L[1,…4] and R[1…4] into one sorted array [1…7]; (see figure b-h)
A 10
1 2 3 4 5 1 2 3 4
L 20 30 40 70 R 10 50 60
i j
(b)
55
Design Techniques
1
10 20
1 2 3 4 5 1 2 3 4
L 20 30 40 70 R 10 50 60
i j
(c)
1 2 3
A 10 20 30
1 2 3 4 5 1 2 3 4
L 20 30 40 70 R 10 50 60
i j
(d)
1 2 3 4
10 20 30 40
1 2 3 4 5 1 2 3 4
L 20 30 40 70 R 10 50 60
i j
(e)
1 2 3 4 5 6 7
10 20 30 40 50
1 2 3 4 5
L 20 30 40 70 R 10 50 60
i j
(f)
56
1 2 3 4 5 7
Divideand Conquer
10 20 30 40 50 60 Approach
1 2 3 4 5
L 20 30 40 70 R 10 50 60
i J
(g)
1 2 3 4 5 6 7
10 20 30 40 50 60 70
1 2 3 4 5
L 20 30 40 70 R 10 50 60
i j
(h)
For simplicity, assume that n is a power of 2 each divide step yields two
sub- problem, both of size exactly n/2.
- (1)
57
Design Techniques
1) Master Method:
-- (1)
We have: a = 2
b=2
flog(n)a = nlog 2
n =n = n ; Now compare f(n) with nlog 2 i-e (n log 2 = n)
b 2 2 2
log 2
Since f(n) = n = O (n 2 ) Case 2 of Master Method
T (n) = (nlogba. logn)
= (n. logn)
Recursion tree:
C. n C.n
C. n
C. n
C. C. C.n
C. C.
Log2 n
C. C. C. C. C.n
T T T T
Figure A
C C C C C C C C C.n
Figure B
2.4.2 QUICK-SORT
Quick-Sort, as its name implies, is the fastest known sorting algorithm in practice.
The running time of Quick-Sort depends on the nature of its input data it receives for
sorting. If the input data is already sorted, then this is the worst case for quick sort. In
58
this case, its running time is O (n2). Inspite of this slow worst case running time,
Quick sort is often the best practical of this choice for sorting because it is Divide and Conquer
Approach
remarkably efficient on the average; its expected running time in (nlogn).
3) Average Case (when input data is not sorted & Partition of array is not
unbalance as worst case) :
Quick Sort
The Quick sort algorithm (like merge sort) closely follows the Divide-and Conquer
strategy. Here Divide-and-Conquer Strategy involves 3 steps to sort a given subarray
A[p..r].
P r
A[1] A[2] - A[n]
1 2 3 n
q
(Sub array of size ) (subarray of size )
The element of A[1…q - 1] The element of A
[q+1..r] is ≤ A[q] is ≥ A[q]
59
Design Techniques These two subarray A [p…q-1] and A[q+1..r] is further divided by recursive call
to QUICK-SORT and the process is repeated till we are left with only one-element
in each sub-array (or no further division is possible).
p
……. …… ………
QUICKSORT (A, p, r) uses a procedure Partition (), which always select a last
element A[r], and set this A[r] as a Pivot element at some index (say q) in the
array A[p..r].
The PARTITION () always return some index (or value), say q, where the array
A[p..r] partitioned into two subarray A[p..q-1] and A[q+1…r] such that A[p..q-1]
≤ A[q] and A[q] ≤ A[q+1…r].
60
Pseudo code for PARTITION: Divide and Conquer
Approach
PARTITION (A, p, r)
4: if A[j] ≤ r A [r]
5: i←i+1
8: return ( i+ 1)
}
The running time of PARTITION procedure is (n), since for an array A[a…n], the
loop at line 3 is running 0(n) time and other lines at code take constant time i.e. 0(1)
so overall time is 0(n).
A 2 8 7 1 3 5 6 4
1 2 3 4 5 6 7 8
x ← A*r+ =
4 I ← p-1 =
0 p r
2 8 7 1 3 5 6 4
i 1 2 3 4 5 6 7 8
61
Design Techniques
b)
2) j = 2; if A*2+ ≤ 4 i.e 8 ≤ 4 No
So line 5 – 6, will not be executed
Thus:
p r
2 8 7 1 3 5 6 4
i
c)
3) j = 3; if A*3+ ≤ 4 i.e 7 ≤ 4 No; so line 5-6 will not execute
4) j = 4; if A*4+ ≤ 4 i.e 1 ≤ 4 YES
So i ← i + 1 = 1 + 1 = 2
exchange (A*2+ ↔ A*4+)
1 2 3 4 5 6 7 8
2 81 7 1 8 3 5 6 4
i
d)
e)
6) j = 6; A*6+ ≤ 4 i.e 5≤ 4 NO
7) j = 7: A *7+ ≤ 4 i.e 6 ≤ 4 NO
Now for loop is now finished; so finally line 7 is execute i.e
exchange (A*4+ ↔ A*8+), so finally we get:
1 2 3 4 5 6 7 8
2 1 3 4 7 5 6 8
i
Finally
we return (i + 1) i.e (3 + 1) = 4; by this partition procedure;
Now we can easily see that all the elements of A*1, … 3+ ≤ A*4+; and
all the elements of A*5, ..8+ ≥ A*4+. Thus
i
2 1 3 4 7 5 6 8
To sort the entire Array A{1..8}; there is a Recursive calls to QuickSort on both the subarray
A*..3+ and A*5…8+.
62
Divide and Conquer
Performance of Quick Sort Approach
The running time of QUICK SORT depends on whether the partitioning is balanced or
unbalanced. Partitioning of the subarrays depends on the input data we receive for
sorting.
Best Case: If the input data is not sorted, then the partitioning of subarray is balanced;
in this case the algorithm runs asymptotically as fast as merge-sort (i.e. 0(nlogn)).
Worst Case: If the given input array is already sorted or almost sorted, then the
partitioning of the subarray is unbalancing in this case the algorithm runs
asymptotically as slow as Insertion sort (i.e. (n2)).
n- elements
≈ elements ≈ elements
≈ ≈ ≈ ≈
n- elements
(n-1) elements
(n-2) elements
(n-3) elements
1
(b) Worst Case
63
Design Techniques
≈ n⁄10 elements
The best case behaviour of Quicksort algorithm occurs when the partitioning
Method 1: Using Master Method; we have a=2; b=2, f(n)=n and nlog ba = nlog 22 = n
C.n
Log2n
C.n
C C C C C C C C C.n
The worst case behaviour for QuickSort occurs, when the partitioning procedures one
region with (n-1) elements and one with 0-elements → completely unbalanced
partition.
In this case:
Recursion Tree:
C.n C.n
C.(n-1) o C.(C-1)
n C.(n-2) o C.(C-2)
C.2 C.2
C.1 o C.1
= = 0(n2)
Average Case
Quick sort average running time is much closer to the best case.
Suppose the PARTITION procedure always produces a 9-to-1 split so recurrence can
be:
65
Design Techniques
Recursion Tree:
C.n C.n
Log10/9n C.n
Log10n
C.n
(Objective questions)
1) Which of the following algorithm have same time complexity in Best, average
and worst case:
a) Quick sort b) Merge sort c) Binary search d) all of these
c) d)
66
70 35 5 85 45 88 50 10 60
7) Show that the running time of MERGESORT algorithm is Divide and Conquer
Approach
8) Illustrate the operation of PARTITION Procedure on the array
10) Show that the running time of QUICKSORT algorithm in the best case is
11) Show that the running time of QUICKSORT algorithm is when all
elements of array A have the same value.
12) Find the running time of QUICKSORT algorithm when the array A is sorted
in non increasing order.
Note: The algorithm, which we are discussing here, works for any number base, e.g.,
binary, decimal, hexadecimal etc. For simplicity matter, we use decimal
number.
The straight forward method (Broute force method) requires 0(n2) time to multiply two
n-bit numbers. But by using divide and conquer, it requires only 0(nlog 23) i.e. 0(n1.59)
time.
A Divide & Conquer based algorithm splits the number X and Y into ②equal parts as:
X= a b = xn-1 xn-2------------X X ┌n/2┐-----------------1 = a × 10 n/2
+
┌n/2┐ x0 b
n/2 n/2
n/2 n/2
67
Design Techniques Note: Both number X and Y should have same number of digits; if any number has
less number of digits then add zero‘s at most-significant bit position. So that we can
If X = 1026732
Y = 743914
Then X = 1026732 = 1026 x 103 + 732
Y = 0743914 = 0743 x 103 + 914
Now we can compute the product as:
Z = X.Y
After solving this recurrence using master method, we have: T(n) = θ(n2); So direct
(or Brute force) method requires O (n2) time.
if n 1
0(1)
T (n) =
3T (n / 0(n)
2)
Otherwise
Where 0(n) is the cost of addition, subtraction and digit shift (multiplications by
power of 10‘s), all these takes time proportional to ‗n‘.
68
Method 1: - (Master Method)
Divide and Conquer
Approach
a=3
b=2
f(n) = n
nlogba = nlog23
f(n)=n=0(nlog 23-є) case 1 of Master Method
T(n) = θ(nlog23)
θ(n1.59)
Method 2 (Substitution Method)
=
Now
69
Design Techniques
=
=
=
=
The product matrix C = A.B. = (Cij)i, j =1…n is also an (n x n) matrix, whose (i,j)th
elements is defined as:
The divide and conquer strategy is yet another way to compute the product of two (n x n)
matrices. Assuming that n is an exact power of 2 (i.e. n=2k). We divide each of A,
B and C into four
n n
matrices. i.e.
2 2
and B = where each Aij and Bij are sub matrices of size
n n
,
2 2
70
Divide and Conquer
Algorithm Divide and Conquer Multiplication (A,B) Approach
1. n ← no. of rows of A
2. if n = 1 then return (a11 b11)
3. else
4. Let Aij, Bij (for i,j = 1,2, be n n
submatrices)
2 2
S.t and
7. Return
matrices).
Line 6 requires 4 = 2
)
So the overall computing time, T(n), for the resulting Divide and conquer Matrix
Multiplication
T(n) = 8T + 2)
Now we can see by using V. Stressen‘s Method, we improve the time complexity of
matrix multiplication from O(n3) to O (n2.81).
71
Design Techniques
3) Strassen’s Method
Volker Strassen had discovered a way to compute the Cij of Eg. (2) using only (7)
multiplication and (18) additions / subtractions.
1) Let
P1 = (A11+A22) (B11+B22)
P2 = (A21+A22).B11
P3 = A11 (B12-B22)
P4 = A22 (B21-B11) (I)
P5 = (A11+A12).B22
P6 = (A21-A11) (B11+B12)
P7 = (A12-A22) (B21+B22)
C1 = P1+ P4 – P5 + P7
C12 = P3+ P5
(II)
C21 = P2+ P4
C22 = P1+ P3 - P2 + P6
(1) n 2
T(n) =
7T n2 Otherwise
72
Divide and Conquer Approach
Strassen showed how the matrix C can be computed using only 7 block
multiplications and 18 block additions or subtractions (12 additions and 6
subtractions):
= x =
C11 = P21 + P4 – P5 + P7 =
C12 = P3 + P5 =
C21 = P2 + P4 =
C22 = P1 + P3 – P2 + P6 =
73
Design Techniques
C =
0(1) if n 1
T (n)
7T (n / 0(n2 )
2)
Otherwise
a = 7; b = 2; f(n) = n2
log a log 7 2.81
n b =n 2 = n
= Q (n2.81).
(Objective questions)
A= B=
2.7 SUMMARY
Many useful algorithms are recursive in structure as they make a recursive call to
itself until a base (or boundary) condition of a problem is not reached. These
algorithms closely follow the Divide and Conquer approach.
Divide and Conquer is a top-down approach, which directly attack the complete
instance of a given problem and break down into smaller parts.
Where
T(n) = running time of a problem of size n
a means ―In how many part the problem is divided‖
means ―Time required to solve a sub-problem each of size (n/b)‖
D(n) + C(n) = f(n) is the summation of the time requires to divide the problem
and combine the sub-solutions.
75
Design Techniques The following table summarizes the recurrence relations and time complexity
of the various problems solved using Divide-and-conquer.
Strassen‘s
matrix case:
Worst
multiplication
Worst case:
2.8 SOLUTIONS/ANSWERS
Worst case:
Since at each iteration, the array is divided into two sub-arrays but we are solving only
one sub-array in the next iteration. So value of a=1 and b=2 and f(n)=k where k is a
constant less than n.
76
Divide and Conquer
; by solving this recurrence using substitution method, Approach
we have:
Using any method such as Recursion-tree or Master Method (as given in UNIT-1), we
have .
Solution 8:
Let
1 2 3 4 5 6 7 8 9 10
A[1…10] = 35 10 40 5 60 25 55 30 50 25
x
Here p = 1 r = 10
(1)
(2)
i.e.,
p r
1 2 3 4 5 6 7 8 9 10
10 35 40 5 60 25 55 30 50 25
i
77
Design Techniques
(3)
(4)
i.e.,
1 2 3 4 5 6 7 8 9 10
10 5 40 35 60 25 55 30 50 25
i
(5)
(6) j
i.e.,
1 2 3 4 5 6 7 8 9 10
10 5 25 35 60 40 55 30 50 25
i
(7)
(8)
78
Divide and Conquer
Approach
(9)
i.e.,
1 2 3 4 5 6 7 8 9 10
10 5 25 20 60 40 50 30 50 35
i
Here PARTITION procedure finally return index (i+1)=4, where the array gets
partitioned. Now the two sub-arrays are
15 1 25 60 40 50 25 50 36
Solution 10: A recurrence relation for QUICKSORT algorithm for best case can be
written as:
Using any method such as Recursion-tree or Master Method (as given in UNIT-1), we
have .
Solution 11: when all elements of array A have the same value, then we have a worst
case for QUICKSORT and in worst case QUICKSORT algorithm requires
time.
Solution 12: when the array A is sorted in non increasing order, then we have a
worst case for QUICKSORT and in worst case QUICKSORT algorithm requires
time.
Solution 6
1026732 × 732912
Though, the above may be simplified in another simpler way, yet we want to
explain Karatsuba‘s method, therefore, next, we compute the products.
U = 1026 × 732
V = 732 × 912
P = 1758 × 1644
Let us consider only the product 1026 × 732 and other involved products may
be computed similarly and substituted in (A).
Let us write
2
U = 1026 × 732 = (10 × 10 + 26) (07 × 102 + 32)
4
= (10 × 7) 10 + 26 × 32 + [(10 + 7) (26 + 32)
2
— 10 × 7 ─ 26 × 32)] 10
4 2
= 17 × 10 + 26 × 32 + (17 × 58 ─ 70 ─ 26 × 32) 10
At this stage, we do not apply Karatsuba‘s algorithm and compute the products of 2-
digit numbers by conventional method.
Solution7:
Accordingly,
, , ,
80
From the above products, we can compute C as follows: Divide and Conquer
Approach
C1 = P1+ P4 – P5 + P7 =[120]+[35]-[72]-[60]=[23]
C12 = P3+ P5 = [-20]+[72]=[52]
C21 = P2+ P4 = [13]+[35]=[48]
C22 = P1+ P3 - P2 + P6 =[120]+[-20]-[13]+[6]=[93]
81
UNIT 3 GRAPH ALGORITHMS
Structure Page Nos.
3.0 Introduction 82
3.1 Objectives 82
3.2 Basic Definition and Terminologies 83
3.3 Graph Representation 85
3.3.1 Adjacency Matrix
3.3.2 Adjacency List
3.4 Graph Traversal Algorithms 87
3.4.1 Depth First Search
3.4.2 Breadth First Search
3.5 Summary 98
3.6 Solutions/Answers 98
3.7 Further Readings 100
3.0 INTRODUCTION
The vast majority of computer algorithm operate on data. Organsing these data in a
certain way (i.e. data structure) has a significant role is design and analysis of
algorithm. Graph is one such fundamental data structure. Array, linked list, stack,
queue, tree, sets are other important data structures. A graph is generally used to
represent connectivity information i.e. connectivity between cities for example.
Graphs have been used and considered very interesting data structures with a large
number of applications for example the shortest path problem. While several
representations of a graph are possible, we discuss in the unit the two most common
representations of a graph: adjacency matrix and adjacency list. Many graph
algorithms requires visiting nodes and vertices of a graph. This kind of operation is
also called traversal. You must have read various traversal methods for tree such as
preorder, postorder and inorder In this unit we present two graph traversal algorithms
which are called as Depth first search and Breadth first search algorithm.
3.1 OBJECTIVES
After going through this unit you will be able to
define a graph,
82
Graph Algorithms
3.2 BASIC DEFINITION AND TERMINOLOGIES
A graph G = (V. E) is a set of vertices V, with edges connecting some of the vertices
(edge set E). An edge between vertex u and v is denoted as (u, v). There are two
types of a graph: (1) undirected a graph and directed graph (digraph). In a undirected
graph the edges have no direction whereas in a digraph all edges have direction.
You can notice that edges have no direction. Let us have an example of an undirected
graph (figure 1) and a directed graph (figure 2)
1 3 4
2 5
V = {0, 1, 2, 3, 4, 5}
(2, 3),
(4, 5)
1 3 4
2 5
Figure 2: Diagraph
V = {0, 1, 2, 3, 4, 5, }
E = { (0, 1),
(1, 2)
83
Design Techniques (3, 4), (3, 5)
(4, 5) and (5, 4) are not the same. These are two different edges.
(5, 4)
The geometry of drawing has no particular meaning: edges of a graph can be drawn
“straight” or “curved”.
PATH
An edge may not have a weight. A path in a graph is sequence of vertices V1 V2….Vn
such that consecutive vertices Vi Vi + 1 have an edge between them, i.e., Vi + 1 is
adjacent to Vi
A path in a graph is simple if all vertices are distinct i.e. no repetition of a path of any
vertices (and therefore edges) in the sequence, except possibly the first and the last
one. Length of a path is the number of edges in the path. A cycle is a path of length at
least 1 such that the first and the last vertices are equal. A cycle is a simple path with
the same vertex as the first and the last vertex in the sequence if the path is simple.
For undirected graph, we require a cycle to have distinct edges. Length of a cycle is
the number of edges in the cycle.
There are many problems in computer science such as of route with minimum
time and diagnostic: minimum shortcut path routing, traveling sales problem etc.
can be designed using paths obtained by marking traversal along the edges of a
graph.
CONNECTED GRAPHS
Connectivity: A graph is connected if there is a path from every vertex to every other
vertex. In an undirected graph, if there is a path between every pair of distinct
vertices of the graph, then the undirected graph is connected. The following example
illustrates this:
a b
a c
b c
d e
f
G1 G2
d e
In directed graph, two vertices are strongly connected if there is a (directed) path
from one to the other.
Undirected: Two vertices are connected if there is a path that includes them.
Directed: Two vertices are strongly-connected if there is a (directed) path from any
vertex to any other.
In this section, we will study the two more important data structure for graph
representation: Adjacency matrix and Adjacency list.
(ii) The adjacency matrix for a directed graph need not be symmetric.
For example for the graph in the following figure (a) is adjacency matrix is given
in (b)
1 4 5
2 3
Figure. 4 (a)
1 2 3 4 5
1 0 1 0 1 0
2 1 0 1 0 1
1 1 0 1 1
3
0 0 1 0 1
0 0 1 1 0
85
Design Techniques Let us answer the following questions:
(i) Suppose if we want to know how much time will take in finding number of edges
a graph with n vertices?
Since the space needed to represent a graph is n2 bits where n is a number of vertices.
All algorithm will require at least 0 (n2) time because n2 – n entries of the matrix have
to be examined. Diagonal entries are zero.
(ii) Suppose the most of the entries in the adjacency matrix are zeros, i.e., when a
graph is a sparse... How much time is needed to the find m number of edges in a
graph? It will take much less time if say 0 (e + n), where e is the number of edges is
a graph and e << n2/2. But this can be achieved if a graph is represented through an
adjacency list where only the edges will be represented.
The adjacency list of a graph or a diagraph is a set of linked lists, one linked list for
each vertex. The nodes in the linked list i contain all the vertices that are adjacent to
vertex i of the list (i.e. all the vertices connected to it by an edge). The following
figure.5 represents adjacency list of the graph in figure 4 (a).
Vertex 1 2 4
Vertex 2 3
1
Vertex 3
2 4 5
Vertex 4
Vertex 5 1 3 5
4 3
What is the storage requirement (in terms of bits) for a adjacency list of any graph!
(i) For storing n (n vertices) head nodes – we require – log2 n bits –
(ii) For storing list nodes for each head n nodes – we require log n + log e
Therefore total storage requirement in item of bits for adjacency matrix is 2log2n
(2log n + log e)
2 2
It may be done in just 0 (n + e) because in degree of any vertex (i.e. number of edges
incident to that vertex) in an undirected graph may be determined by just counting
the number of nodes in its adjacency list.
86
Use of adjacency matrix or adjacency list for representing your graph – depends upon
Graph Algorithms
the type of a problem; type of algorithm to be used for solving a problem and types
of a input graph (dense or sparse)
You are aware of tree traversal mechanism. Give a tree, you can traverse it using
preorder, inorder and postorder. Similarly given an undirected graph you can traverse
it or visit its nodes using breadth first-search and depth-first search.
Searching in breadth-first search or depth first search means exploring a given graph.
Through searching a graph one can find out whether a graph is connected or not?
There are many more applications of graph searching algorithms. In this section we
will illustrate Depth First Search algorithm followed by Breadth first Search algorithm
in the next section.
The logic behind this algorithm is to go as far as possible from the given starting
node searching for the target. In case, we get a node that has no adjacent/successor
node, we get back (recursively) and continue with the last vertex that is still not
visited.
Before starting with an algorithm, let us discuss the terminology and structure used in
the algorithm. The following algorithm works for undirected graph and directed
graph both.
The following color scheme is to maintain the status of vertex i.e mark a vertex is
visited or unvisited or target vertex:
Let us write the algorithm DFS for any given graph G. In graph G, V is the vertex set
and E is the set of edges written as G(V,E). Adjacency list for the given graph G is
stored in Adj array as described in the previous section.
color[] - An array color will have status of vertex as white or gray or black as defined
earlier in this section.
87
Design Techniques DFS(G)
{
for each v in V, //for loop V+1 times
{
color[v]=white; // V times
p[v]=NULL; // V
times
}
time=0; // constant time O(1)
for each u in V, //for loop V+1
times if (color[u]==white) // V times
DFSVISIT(u) // call to DFSVISIT(v) , at most V times O(V)
DFSVISIT(u)
{
color[u]=gray; // constant
time t[u] = ++time;
for each v in Adj(u) // for loop
if (color[v] == white)
{
p[v] = u;
DFSVISIT(v); // call to DFSVISIT(v)
}
color[u] = black; // constant time
f[u]=++time; // constant time
}
Complexity analysis
In the above algorithm, there is only one DFSVISIT(u) call for each vertex u in the
vertex set V. Initialization complexity in DFS(G) for loop is O(V). In second for loop
of DFS(G) , complexity is O(V) if we leave the call of DFSVISIT(u).
Now, Let us find the complexity of function DFSVISIT(u)
The complexity of for loop will be O(deg(u)+1) if we do not consider the recursive
call to DFSVISIT(v). For recursive call to DFSVISIT(v), (complexity will be O(E)
as Recursive call to DFSVISIT(v) will be at most the sum of degree of adjacency for
all vertex v in the vertex set V. It can be written as |Adj(v)|=O(E)
v V
Hence, overall complexity for DFS algorithm is O(V + E)
88
The strategy of the DFS is to search “deeper” in the graph whenever possible.
Graph Algorithms
Exploration of vertex is in the fashion that first it goes deeper then widened.
Let us take up an example to see how exploration of vertex takes place by Depth First
Search algorithm.
89
Design Techniques
90
Graph Algorithms
Now each vertex of the given graph is visited/explored by DFS algorithm and
DFS tree is as follows:
91
Design Techniques
Data structure used for implementing DFS algorithm is stack. In the diagram along
with each vertex start and finish time is written in the format a/b here a represent start
time and b represent finish time. This will result in to tree or forest. The order of
vertices explored by DFS algorithm according to adjacency list considered for given
graph is 1,2,3,4,5.
In this section, we will discuss breadth first search algorithm for graph. This is very
well known searching algorithm. A traversal depends both on the starting vertex, and
on the order of traversing the adjacent vertices of each node. The analogy behind
breadth first search is that it explores the graph wider then deeper. The method starts
with a vertex v then visit all its adjacent nodes v1,v2,v3…then move to the next node
which is adjacent to v1, v2, v3 …. This also referred as level by level search.
Now, let us see the structure used in this algorithm and color scheme for status of
vertex.
Color scheme is same as used in DFS algorithm i.e to maintain the status of vertex i.e
mark a vertex is visited or unvisited or target vertex:
The structure given below is used in the algorithm. G will be the graph as G(V,E) with
set of vertex V and set of edges E.
Data structure used for breadth-first search is queue, Q (FIFO), to store gray
vertices. color[v]- This array will keep the status of vertex as white, grey or black
92
The following algorithm for BFS takes input graph G(V,E) where V is set of vertex
Graph Algorithms
and E is the set of edges. Graph is represented by adjacency list i.e Adj[]. Start vertex
is s in V.
Line BFS(G,s)
No. {
1. for each v in V - {s} // for loop
{
2. color[v]=white;
3. d[v]= INFINITY;
4. p[v]=NULL;
}
5. color[s] = gray;
6. d[s]=0;
7. p[s]=NULL;
8. Q= // Initialize queue is empty
;
9. Enqueue(Q,s); /* Insert start vertex s in Queue Q */
10. while Q is nonempty // while loop
{
11. u = Dequeue[Q]; /* Remove an element from Queue Q*/
93
Design Techniques In this algorithm first for loop executes at most O(V) times.
While loop executes at most O(V) times as every vertex v in V is enqueued only once
in the Queue Q. Every vertex is enqueued once and dequeued once so queuing will
take at most O(V) time.
Inside while loop, there is for loop which will execute at most O(E) times as it will be
at most the sum of degree of adjacency for all vertex v in the vertex set V.
v V
Let us summarize the number of times a statement will execute in the algorithm for
BFS.
1 V O(V)
2 V-1
3 V-1
4 V-1 O(1)
5 1
6 1
7 1
8 1
9 1
10 V+1 O(V)
11 V
12 V+E+1 O(V+E)
13 V+E
14 V
15 V
16 V
17 V
18 V
94
Let us take up an example to see how exploration of vertex takes place by Breadth
Graph Algorithms
First Search algorithm.
95
Design Techniques
96
Graph Algorithms
Q = Ø
After exploring the vertex of given graph by BFS algorithm, BFS traversal sequence
is
1, 2, 3, 4, 5
In this algorithm sequence of vertex visited or explored may vary. The final sequence
of vertex visited is dependent on adjacency list. But the array d[] will have same
number irrespective of order of vertices in adjacency list. In the above diagram
distance is shown along the vertex. According to adjacency list drawn in the diagram,
exploration sequence of vertex by BFS algorithm is 1,2,3,4,5.
97
Design Techniques 3. Consider a graph with 5 vertices and 6 edges. Write its adjacency matrix and
adjacency list.
V1
V3
V2
V4 V5
4. For the following graph write DFS and BFS traversal sequence.
C
B
D G
E F
3.5 SUMMARY
A graph G(V,E) where V is the finite set of vertices i.e { v1,v2,v3….} and E is the
finite set of edges {(u,v),(w,x)….}. Graph is known as directed graph if the each edge
in the graph has ordered pair of vertices i.e (u,v) means an edge from u to v. In
Undirected graph each edge is unordered pair of vertices i.e (u,v) and (v,u) refers to
the same edge. A graph can be represented by adjacency matrix and adjacency list. In
adjacency, list memory requirement is more as compared to adjacency list
representation. Graph searching problem has wide range of applications. Breadth
First search and Depth first search are very well known searching algorithms. In
breadth first search, exploration of vertex is wider first then deeper. In depth first
search it is deeper first and then it is widened. By exploration of vertex in any search
algorithm, implies visiting or traversing each vertex in the graph. Data structure used
for Breadth first search is queue and depth first search is stack. By using these search
algorithms, connected components of graph can be found. Breadth first search
method, gives shortest path between two vertices u and v. Depth first search is used in
topological sorting. There are many more applications where these searching
algorithms are used.
3.6 SOLUTIONS/ANSWERS
Check Your Progress 1
98
For DFS algorithm complexity is as
Graph Algorithms
follows: Adjacency Matrix – O(V2)
Adjacency List – O(V+E)
Adjacency Matrix
V1 V2 V3 V4 V5
V1 0 1 1 0 0
V2 1 0 1 1 0
V3 1 1 0 0 1
V4 0 1 0 0 1
V5 0 0 1 1 0
Adjacency List
V1
V2 V3
V2
V1 V3 V4
V3
V1 V2 V5
V4
V2 V5
V5
V3 V4
99
Design Techniques 4. For the given graph
C
B
D G
E F
100