02512tpnews 11082020
02512tpnews 11082020
Algorithms (BCS-28)
[B Tech IIIrd Year, Vth Sem, Session: 2020-21]
Course Outcomes The students are expected to be able to demonstrate the following
knowledge, skills and attitudes after completing this course.
1. Define the basic concepts of algorithms and analyze the performance of algorithms.
2. Discuss various algorithm design techniques for developing algorithms.
3. Discuss various searching, sorting and graph traversal algorithms.
4. Understand NP completeness and identify different NP complete problems.
5. Discuss various advanced topics on algorithm
UNIT-I
Introduction: Algorithms, Analyzing Algorithms, Complexity of Algorithms, 9
UNIT-II
Greedy Methods with Examples such as Optimal Reliability Allocation, Knapsack, 9
UNIT-III
Backtracking, Branch and Bound with Examples such as Travelling
Salesman Problem, Graph Coloring, N-Queen Problem, Hamiltonian
Cycles and Sum of Subsets
Advanced Data Structures: Red-Black Trees, B – Trees, Binomial
Heaps, Fibonacci Heaps.
UNIT-IV
Selected Topics: String Matching, Text Processing- Justification of
Text, Theory of NP-Completeness, Approximation Algorithms and
Randomized Algorithms, Algebraic Computation, Fast Fourier
Transform.
EXPERIMENTS
1. To analyze time complexity of Insertion sort.
2. To analyze time complexity of Quick sort.
3. To analyze time complexity of Merge sort.
4. To Implement Largest Common Subsequence.
5. To Implement Matrix Chain Multiplication.
6. To Implement Strassen‟s matrix multiplication Algorithm, Merge sort and Quick sort.
7. To implement Knapsack Problem.
8. To implement Activity Selection Problem.
9. To implement Dijkstra‟s Algorithm.
10. To implement Warshall‟s Algorithm.
11. To implement Bellman Ford‟s Algorithm.
12. To implement Naïve String Matching Algorithm.
13. To implement Rabin Karp String Matching Algorithm
14. To implement Prim‟s Algorithm.
15. To implement Kruskal‟s Algorithm.
Textbooks
1. Thomas H. Coreman, Charles E. Leiserson and Ronald L. Rivest, Introduction
to Algorithms, PHI.
2. RCT Lee, SS Tseng, RC Chang and YT Tsai, “Introduction to the Design and
Analysis of Algorithms”, McGraw Hill, 2005.
3. Ellis Horowitz and Sartaj Sahni, Fundamentals of Computer Algorithms,
Computer Science Press, Maryland, 1978
4. Berman, Paul,” Algorithms”, Cengage Learning.
5. Aho, Hopcraft, Ullman, “The Design and Analysis of Computer Algorithms”
Pearson Education, 2008.
Reference books
1. Berlion, P. Izard, P., Algorithms-The Construction, Proof and Analysis of
Programs, 1986. Johan Wiley & Sons.
2. Bentley, J.L., Writing Efficient Programs, PHI
3. Ellis Horowitz, Sartaj Sahni, and Sanguthevar Rajasekaran, Computer
Algorithms, W. H. Freeman, NY, 1998
4. Goodman, S.E. & Hedetnien, introduction to Design and Analysis of
Algorithm1997, MGH.
8/25/2020 5. Knuth, D.E , Fundamentals of Algorithms:
DAA - Unit - I Presentation The
SlidesArt of Computer Programming 6
Vol,1985
UNIT – I
algorithm
Algorithms for the same problem can be based on very different ideas and can solve
the problem with dramatically different speeds.
The greatest common divisor of two nonnegative, not-both-zero integers m and n,
denoted gcd(m, n), is defined as the largest integer that divides
both m and n evenly.
In modern terms, Euclid’s algorithm is based on applying repeatedly the equality
while n = 0 do
r ← m mod n
m←n
n ← r return m
II. Middle-school procedure for computing gcd(m, n)
Step 1 Find the prime factors of m.
Step 2 Find the prime factors of n.
Step 3 Identify all the common factors in the two prime expansions found in Step
1 and Step 2.
(If p is a common factor occurring pm and pn times in m and n, respectively, it
should be repeated min{pm, pn} times.)
Step 4 Compute the product of all the common factors and return it as
the greatest common divisor of the numbers given.
24 = 2 . 2 . 2 . 3
gcd(60, 24) = 2 . 2 . 3 = 12.
Characteristics of an Algorithm
• Input
• Output
• Definiteness
• Finiteness
• Effectiveness
• Correctness
• Simplicity
• Unambiguous
• Feasibility
• Portable
• Independent
Apriori and posteriori Analysis
• Apriori analysis means, analysis is performed prior to running it on a specific
system. This analysis is a stage where a function is defined using some theoretical
model.
Hence, we determine the time and space complexity of an algorithm by just looking
at the algorithm rather than running it on a particular system with a different
memory, processor, and compiler.
One circumstance to be aware of is, does the approach require the data to be
duplicated in memory (as does merge sort). If so we have 2N memory use.
Time efficiency
The actual running time depends on many factors:
•The speed of the computer: cpu (not just clock speed), I/O, etc.
•The compiler, compiler options .
•The quantity of data - ex. search a long list or short.
•The actual data - ex. in the sequential search if the name is first or last.
◼ A faster algorithm running on a slower machine will always win for large enough
instances
◼ Suppose algorithm S1 sorts n keys in 2n2 instructions
◼ Suppose computer C1 executes 1 billion instruc/sec
◼ When n = 1 million, takes 2000 sec
4. Branch and Bound: In Branch & Bound algorithm a given subproblem, which
cannot be bounded, has to be divided into at least two new restricted subproblems.
Branch and Bound algorithm are methods for global optimization in non-convex
problems. Branch and Bound algorithms can be slow, however in the worst case they
require effort that grows exponentially with problem size, but in some cases we are
lucky, and the method coverage with much less effort.
• The running time depends on the input: an already sorted sequence is easier to
sort.
• Major Simplifying Convention: Parameterize the running time by the size of
the input, since short sequences are easier to sort than long ones.
➢TA(n) = time of A on length n inputs
• Generally, we seek upper bounds on the running time, to have a guarantee of
performance.
L1.29
Kinds of analyses
Worst-case: (usually)
• T(n) = maximum time of algorithm on any input of size n.
Average-case: (sometimes)
• T(n) = expected time of algorithm over all inputs of size n.
• Need assumption of statistical distribution of inputs.
Best-case: (NEVER)
• Cheat with a slow algorithm that works fast on some input.
L1.30
Methodology of Analysis
• Asymptotic Analysis
• The asymptotic behavior of a function f(n) refers to the growth of f(n) as n
gets large.
• We typically ignore small values of n, since we are usually interested in
estimating how slow the program will be on large inputs.
• A good rule of thumb is that the slower the asymptotic growth rate, the
better the algorithm. Though it’s not always true.
• For example, a linear algorithm f(n)=d∗n+k is always asymptotically better
than a quadratic one, f(n)=c. n2+q.
Methodology of Analysis
• Solving Recurrence Equations
• A recurrence is an equation or inequality that describes a function in terms of its
value on smaller inputs. Recurrences are generally used in divide-and-conquer
paradigm.
• Let us consider T(n) to be the running time on a problem of size n.
• If the problem size is small enough, say n < c where c is a constant, the
straightforward solution takes constant time, which is written as θ(1). If the
division of the problem yields a number of sub-problems with size nb
• A recurrence relation can be solved using the following methods −
• Substitution Method − In this method, we guess a bound and using
mathematical induction we prove that our assumption was correct.
• Recursion Tree Method − In this method, a recurrence tree is formed
where each node represents the cost.
• Master’s Theorem − This is another important technique to find the
complexity of a recurrence relation.
Growth of Function (Asymptotic
Notations)
• The complexity of an algorithm describes the efficiency of the algorithm in terms of
the amount of the memory required to process the data and the processing time.
• Complexity of an algorithm is analyzed in two perspectives: Time and Space.
• Execution time of an algorithm depends on the instruction set, processor speed, disk
I/O speed, etc. Hence, we estimate the efficiency of an algorithm asymptotically.
• Time function of an algorithm is represented by T(n), where n is the input size.
• Different types of asymptotic notations are used to represent the complexity of an
algorithm. Following asymptotic notations are used to calculate the running time
complexity of an algorithm.
• O − Big Oh
• Ω − Big omega
• θ − Big theta
• o − Little Oh
• ω − Little omega
Growth of Function (Asymptotic
Notations)contd..
• O: Asymptotic Upper Bound
• ‘O’ (Big Oh) is the most commonly used notation. A function f(n) can be
represented is the order of g(n) that is O(g(n)), if there exists a value of positive
integer n as n0 and a positive constant c such that −
f(n)⩽c.g(n) for n>n0 in all case
• Hence, function g(n) is an upper bound for function f(n), as g(n) grows faster
than f(n).
Example
• Let us consider a given function, f(n)=4.n3+10.n2+5.n+1
• Considering g(n)=n3
• f(n)⩽5.g(n) for all the values of n>2
• Hence, the complexity of f(n) can be represented as O(g(n)) i.e. O(n3)
Growth of Function (Asymptotic
Notations)Contd...
Big-O Examples
Example 1
Example 2
It is usually assumed the bound is tight. For example, 3n + 4 function is bounded by n2 for n
> 4 and so is O(n2). This is not a tight bound however, 3n + 4 is O(n).
Growth of Function (Asymptotic
Notations)Contd...
• θ: Asymptotic Tight Bound
• We say that f(n)=θ(g(n)) when there exist constants c1 and c2 that
c1.g(n)⩽f(n)⩽c2.g(n)for all sufficiently large value of n. Here n is a positive
integer.
• This means function g is a tight bound for function f.
Example
• Let us consider a given function, f(n)=4.n3+10.n2+5.n+1
• Considering g(n)=n3 , 4.g(n)⩽f(n)⩽5.g(n)for all the large values of n.
• Hence, the complexity of f(n) can be represented as θ(g(n)) , i.e. θ(n3).
Growth of Function (Asymptotic
Notations)Contd...
Growth of Function (Asymptotic
Notations)Contd...
• Ω: Asymptotic Lower Bound
• We say that f(n)=Ω(g(n))
f(n)=Ω(g(n)) when there exists constant c that f(n)⩾c.g(n),
f(n)⩾c.g(n) for all sufficiently large value of n. Here n is a positive integer. It
means function g is a lower bound for function f; after a certain value of n, f will
never go below g.
Example
• Let us consider a given function, f(n)=4.n3+10.n2+5.n+1
• Considering g(n)=n3, f(n)⩾4.g(n) for all the values of n>0.
• Hence, the complexity of f(n) can be represented as Ω(g(n)), i.e. Ω(n3)
Growth of Function (Asymptotic
Notations)Contd...
Common Asymptotic Notations
Function Big-O Name
1 O(1) constant
log n O(log n) logarithmic
n O(n) linear
n log n O(n log n) n log n
n2 O(n2) quadratic
n3 O(n3) cubic
2n O(2n) exponential
n! O(n!) factorial
Rate of growth of function
Logarithmic Linear Linear Quadratic Polynomial Exponential
logarithmic
Log2n N nlog2n n2 n3 2n
0 1 0 1 1 2
1 2 2 4 8 4
2 4 8 16 64 16
3 8 24 64 512 256
4 16 64 256 4096 65536
5 32 160 1024 32768 4294967296
3.322 10 33.22 102 103 > 103
6.644 102 664.4 104 106 > >1025
9.966 103 9966.0 106 10 > > 10250
T(n) = T(n-1) + n
49
Example Recurrences
• T(n) = T(n-1) + n Θ(n2)
• Recursive algorithm that loops through the input to eliminate one item
• T(n) = T(n/2) + c Θ(lg n)
• Recursive algorithm that halves the input in one step
• T(n) = T(n/2) + n Θ(n)
• Recursive algorithm that halves the input but must examine every item in
the input
• T(n) = 2T(n/2) + 1 Θ(n)
• Recursive algorithm that splits the input into 2 halves and does a constant
amount of other work
50
Analysis of BINARY-SEARCH
Alg.: BINARY-SEARCH (A, lo, hi, x)
if (lo > hi) constant time: c1
return FALSE
mid (lo+hi)/2 constant time: c2
if ( x > A[mid] )
same problem of size n/2
BINARY-SEARCH (A, mid+1, hi, x)
• T(n) = c + T(n/2)
• T(n) – running time for an array of size n
51
Methods for Solving Recurrences
• Iteration method
• Substitution method
• Master method
52
The Iteration Method
• Convert the recurrence into a summation and try to bound it using known series
• Iterate the recurrence until the initial condition is reached.
• Use back-substitution to express the recurrence in terms of n and the initial
(boundary) condition.
53
The Iteration Method
T(n/2) = c + T(n/4)
T(n) = c + T(n/2)
T(n) = c + T(n/2) T(n/4) = c + T(n/8)
= c + c + T(n/4)
= c + c + c + T(n/8)
Assume n = 2k
T(n) = c + c + … + c + T(1)
k times
= clgn + T(1)
= Θ(lgn)
54
Iteration Method – Example
T(n) = n + 2T(n/2) Assume: n = 2k
T(n) = n + 2T(n/2) T(n/2) = n/2 + 2T(n/4)
= n + 2(n/2 + 2T(n/4))
= n + n + 4T(n/4)
= n + n + 4(n/4 + 2T(n/8))
= n + n + n + 8T(n/8)
… = in + 2iT(n/2i)
= kn + 2kT(1)
= nlgn + nT(1) = Θ(nlgn)
55
The substitution method
1. Guess a solution
2. Use induction to prove that the solution works
56
Substitution method
• Guess a solution
• T(n) = O(g(n))
57
Example: Binary Search
T(n) = c + T(n/2)
• Guess: T(n) = O(lgn)
• Induction goal: T(n) ≤ d lgn, for some d and n ≥ n0
• Induction hypothesis: T(n/2) ≤ d lg(n/2)
59
The recursion-tree method
60
Example 1
W(n) = 2W(n/2) + n2
( ) ( ) ( )
i
3 2 3 1
T ( n) = cn + n
16
log 4 3
cn 2 + n log 4 3 =
i =0 16
3
cn 2 + n log 4 3 = O(n 2 )
i =0
1−
16
T(n) = O(n ) 2 62
Master’s method
• Solving recurrences of the form:
n
T (n) = aT + f (n)
b
where, a ≥ 1, b > 1, and f(n) > 0
63
Master’s method
• For solving recurrences of the form:
n
T (n) = aT + f (n)
b
where, a ≥ 1, b > 1, and f(n) > 0
Case 1: if f(n) = O(nlogba -) for some > 0, then: T(n) = (nlogba)
af(n/b) ≤ cf(n) for some c < 1 and all sufficiently large n, then:
T(n) = (f(n))
regularity condition
64
Example
T(n) = 2T(n/2) + n
a = 2, b = 2, log22 = 1
T(n) = (nlgn)
66
Example
T(n) = 2T(n/2) + n2
a = 2, b = 2, log22 = 1
a f(n/b) ≤ c f(n)
T(n) = (n2)
67
Example
T(n) = 3T(n/4) + nlgn
a = 3, b = 4, log43 = 0.793
T(n) = (nlgn)
68
The problem of sorting
Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Example of Insertion Sort
Machine-independent time: An
example
A pseudocode for insertion sort ( INSERTION SORT ).
INSERTION-SORT(A)
1 for j 2 to length [A]
2 do key A[ j]
3 Insert A[j] into the sortted sequence A[1,..., j-1].
4 i j–1
5 while i > 0 and A[i] > key
6 do A[i+1] A[i]
7 ii–1
8 A[i +1] key
Analysis of INSERTION-SORT(contd.)
INSERTION - SORT(A) cost times
1 for j 2 to length [ A] c1 n
2 do key A[ j ] c2 n −1
3 Insert A[ j ] into the sorted
sequence A[1 j − 1] 0 n −1
4 i j −1 c4 n −1
5 while i 0 and A[i ] key c5 n
t
j =2 j
6 do A[i + 1] A[i ] c6 n
(t
j =2 j
− 1)
7 i i −1 c7 n
(t
j =2 j
− 1)
8 A[i + 1] key c8 n −1
Analysis of INSERTION-SORT(contd.)
n n
T (n) = c1 + c2 (n − 1) + c4 (n − 1) + c5 t j + c6 (t j − 1)
j =2 j =2
n
+ c7 (t j − 1) + c8 ( n − 1).
j =2
Analysis of INSERTION-SORT(contd.)
T (n) = c1n + c2 (n − 1) + c4 (n − 1) + c5 (n − 1) + c8 (n − 1)
= (c1 + c2 + c4 + c5 + c8 )n − (c2 + c4 + c5 + c8 ).
Analysis of INSERTION-SORT(contd.)
•The worst case: The array is reverse sorted
(tj =j for j=2,3, ...,n).
n n(n + 1)
j=
j =1 2
T (n) = an 2 + bn + c
Shell Sort
Advantage:
• Advantage of Shellsort is that its only efficient for medium size lists. For bigger
lists, the algorithm is not the best choice. Fastest of all O(N^2) sorting
algorithms.
• 5 times faster than the bubble sort and a little over twice as fast as the insertion
sort, its closest competitor.
Empirical Analysis of Shell sort
Disadvantage:
• Disadvantage of Shellsort is that it is a complex algorithm and its not nearly as
efficient as the merge, heap, and quick sorts.
• The shell sort is still significantly slower than the merge, heap, and quick sorts,
but its relatively simple algorithm makes it a good choice for sorting lists of less
than 5000 items unless speed important. It's also an excellent choice for
repetitive sorting of smaller lists.
Shell sort Best Case
• Best Case: The best case in the shell sort is when the array is already sorted
in the right order. The number of comparisons is less.
Shell sort Worst Case
• The running time of Shellsort depends on the choice of increment sequence.
• The problem with Shell’s increments is that pairs of increments are not
necessarily relatively prime and smaller increments can have little effect.
Shell sort Example
Sort: 18 32 12 5 38 33 16 2
* floor(8/2) ➔ floor(4) = 4
18 32 12 5 38 33 16 2
Sort: 18 32 12 5 38 33 16 2
* floor(8/2) ➔ floor(4) = 4
18 32 12 5 38 33 16 2
* floor(2/2) ➔ floor(1) = 1
increment 1: 1
12 2 16 5 18 32 38 33
2 5 12 16 18 32 33 38
• Combine: The sub arrays are sorted in place – no work is needed to combine
them.
• How do the divide and combine steps of quick sort compare with those of merge
sort?
Pseudocode
Quicksort(A, p, r)
if p < r then Partition(A, p, r)
q := Partition(A, p, r); x, i := A[r], p – 1;
Quicksort(A, p, q – 1); for j := p to r – 1 do
Quicksort(A, q + 1, r) if A[j] x then
i := i + 1;
A[p..r] A[i] A[j]
A[i + 1] A[r];
5 return i + 1
A[p..q – 1] A[q+1..r]
Partition
5
5 5
Example
p r
initially: 2 5 8 3 9 4 1 7 10 6 note: pivot (x) = 6
i j
next iteration: 2 5 8 3 9 4 1 7 10 6
i j Partition(A, p, r)
x, i := A[r], p – 1;
next iteration: 2 5 8 3 9 4 1 7 10 6 for j := p to r – 1 do
i j if A[j] x then
i := i + 1;
next iteration: 2 5 8 3 9 4 1 7 10 6 A[i] A[j]
i j A[i + 1] A[r];
return i + 1
next iteration: 2 5 3 8 9 4 1 7 10 6
i j
Example (contd…)
next iteration: 2 5 3 8 9 4 1 7 10 6
i j
next iteration: 2 5 3 8 9 4 1 7 10 6
i j
next iteration: 2 5 3 4 9 8 1 7 10 6 Partition(A, p, r)
i j x, i := A[r], p – 1;
next iteration: 2 5 3 4 1 8 9 7 10 6 for j := p to r – 1 do
i j if A[j] x then
next iteration: 2 5 3 4 1 8 9 7 10 6 i := i + 1;
i j A[i] A[j]
next iteration: 2 5 3 4 1 8 9 7 10 6 A[i + 1] A[r];
i j return i + 1
after final swap: 2 5 3 4 1 6 9 7 10 8
i j
Partitioning
• Select the last element A[r] in the subarray A[p..r] as the pivot – the element
around which to partition.
• As the procedure executes, the array is partitioned into four (possibly empty)
regions.
1. A[p..i ] — All entries in this region are < pivot.
2. A[i+1..j – 1] — All entries in this region are > pivot.
3. A[r] = pivot.
4. A[j..r – 1] — Not known how they compare to pivot.
• The above hold before each iteration of the for loop, and constitute a loop
invariant. (4 is not part of the loopi.)
Correctness of Partition
• Use loop invariant.
• Initialization:
• Before first iteration
• A[p..i] and A[i+1..j – 1] are empty – Conds. 1 and 2 are satisfied
(trivially).
• r is the index of the pivot
Partition(A, p, r)
• Cond. 3 is satisfied.
x, i := A[r], p – 1;
• Maintenance: for j := p to r – 1 do
• Case 1: A[j] > x if A[j] x then
i := i + 1;
• Increment j only.
A[i] A[j]
• Loop Invariant is maintained. A[i + 1] A[r];
return i + 1
Correctness of Partition
Case 1:
p i j r
>x x
x >x
p i j r
x
x >x
Correctness of Partition
• Case 2: A[j] x • Increment j
• Increment i • Condition 2 is maintained.
• Swap A[i] and A[j] • A[r] is unaltered.
• Condition 1 is maintained. • Condition 3 is
maintained.
p i j r
x x
x >x
p i j r
x
x >x
Correctness of Partition
• Termination:
• When the loop terminates, j = r, so all elements in A are
partitioned into one of the three cases:
• A[p..i] pivot
• A[i+1..j – 1] > pivot
• A[r] = pivot
• The last two lines swap A[i+1] and A[r].
• Pivot moves from the end of the array to between the
two subarrays.
• Thus, procedure partition correctly performs the divide
step.
Complexity of Partition
• PartitionTime(n) is given by the number of
iterations in the for loop.
• (n) : n = r – p + 1.
Partition(A, p, r)
x, i := A[r], p – 1;
for j := p to r – 1 do
if A[j] x then
i := i + 1;
A[i] A[j]
A[i + 1] A[r];
return i + 1
Partitioning in Quick sort
• A key step in the Quick sort algorithm is
partitioning the array
• We choose some (any) number p in the array to use as
a pivot
• We partition the array into three parts:
• Heap Sort is one of the best sorting methods being in-place and with no quadratic
worst-case running time. Heap sort involves building a Heap data structure from
the given array and then utilizing the Heap to sort the array.
• Def: A heap is a nearly complete binary tree with the following two properties:
• Structural property: all levels are full, except possibly the last one, which
is filled from left to right
• Order (heap) property: for any node x
Parent(x) ≥ x
Array Representation of Heaps
• A heap can be stored as an array A.
• Root of tree is A[1]
• Left child of A[i] = A[2i]
• Right child of A[i] = A[2i + 1]
• Parent of A[i] = A[ i/2 ]
• Heapsize[A] ≤ length[A]
119
Heap Types
• Max-heaps (largest element at root), have the max-heap property:
• for all nodes i, excluding the root:
• A[PARENT(i)] ≥ A[i]
A[2] A[4]
A[2] violates the heap property A[4] violates the heap property
A[4] A[9]
2h
O(hh)
• Running time of MAX-HEAPIFY is O(lg n)
Alg: BUILD-MAX-HEAP(A)
1
1. n = length[A] 4
1 3
4 5 6 7
3. do MAX-HEAPIFY(A, i, n)
8
2 9 10
16 9 10
14 8 7
A: 4 1 3 2 16 9 10 14 8 7
Example: A 4 1 3 2 16 9 10 14 8 7
4 4 4
2 3 2 3 2 3
1 3 1 3 1 3
4 5 6 7 4 5 6 7 4 5 6 7
8
2 9 10
16 9 10 8 2 9 10
16 9 10 8 14 9 10
16 9 10
14 8 7 14 8 7 2 8 7
i=2 i=1
1 1 1
4 4 16
2 3 2 3 2 3
1 10 16 10 14 10
4 5 6 7 4 5 6 7 4 5 6 7
8
14 9 10
16 9 3 8
14 9 10
7 9 3 8
8 9 10
7 9 3
2 8 7 2 8 1 2 4 1
Running Time of BUILD MAX HEAP
Alg: BUILD-MAX-HEAP(A)
1. n = length[A]
O(n)
2. for i ← n/2 downto 1 O(lgn)
3. do MAX-HEAPIFY(A, i, n)
h1 = 2 i=1 21
h2 = 1 i=2 22
h3 = 0 i = 3 (lgn) 23
• Idea:
• Build a max-heap from the array
• Swap the root (the maximum element) with the last element in the array
• “Discard” this last node by decreasing the heap size
• Call MAX-HEAPIFY on the new root
• Repeat this process until only one node remains
132
Example: A=[7, 4, 3, 1, 2]
MAX-HEAPIFY(A, 1, 1)
133
Algorithm: HEAPSORT(A)
1. BUILD-MAX-HEAP(A) O(n)
2. for i ← length[A] downto 2
134
Merge Sort
n
• Divide stage: Split the n-element (unsorted)
n/2 n/2
• Combine stage: Merge the two (sorted) (sorted)
sorted subsequences into one sorted
sequence (the solution)
MERGE
n
(sorted)
Merging Sorted Sequences
Merging Sorted Sequences
• Combines the sorted
(1) subarrays A[p..q] and
A[q+1..r] into one sorted
array A[p..r]
(n)
• Makes use of two working
arrays L and R which
initially hold copies of the
(1) two subarrays
• Makes use of sentinel
value () as last element
to simplify logic
(n)
Merge Sort Algorithm
(1)
T(n/2)
T(n/2)
(n)
T(n) = cn(lg n + 1)
= cnlg n + cn
T(n) is (n lg n)
Merge Sort
Analysis of Different Sorting
Algorithms
Comparison based sorting:
2 2 2
Average O(n ) O(n ) O(n ) O(log n) O(log n) O(log n)
Case
2) 2 2 2
Worst O(n O(n ) O(n ) O(log n) O(n ) O(log n)
Case
8/25/2020 DAA - Unit - I Presentation Slides 144
Analysis of Different Sorting
Algorithms :Non Comparison Based
Non-comparison based sorting :
In non-comparison based sorting, elements of array are not compared with each
other to find the sorted array.
• Radix sort
Best, average and worst case time complexity: nk where k is the maximum
number of digits in elements of array.
• Count sort
Best, average and worst case time complexity: n+k where k is the size of count
array.
• Bucket sort
Best and average time complexity: n+k where k is the number of buckets.
Worst case time complexity: n^2 if all elements belong to same bucket.
Summary of time complexity of non-
comparison based Sorting Techniques
Matrix Multiplication Problem
Divide and Conquer
Following is simple Divide and Conquer method to multiply two square matrices.
1) Divide matrices A and B in 4 sub-matrices of size N/2 x N/2 as shown in the below
diagram.
2) Calculate following values recursively. ae + bg, af + bh, ce + dg and cf + dh.
Matrix Multiplication Problem
• Naive matrix multiplication
• Let us start with two square matrices A and B which are both of size n by n. In
the product C = A X B we define the entry cij, the entry in the ith row and the jth
column of A, as being the dot product of the ith row of A with the jth column of
B. Taking the dot product of vectors just means that you take the products of the
individual components and then add up the results.
• Complexity =O(n^3)
Matrix Multiplication Problem
• In the above method, we do 8 multiplications for matrices of size N/2 x N/2 and
4 additions. Addition of two matrices takes O(N2) time. So the time complexity
can be written
• T(N) = 8T(N/2) + O(N2)
• From Master's Theorem, time complexity of above method is O(N3) which is
unfortunately same as the above naive method.
• Simple Divide and Conquer also leads to O(N3), can there be a better way?
In the above divide and conquer method, the main component for high time
complexity is 8 recursive calls. The idea of Strassen’s method is to reduce the
number of recursive calls to 7. Strassen’s method is similar to above simple
divide and conquer method in the sense that this method also divide matrices to
sub-matrices of size N/2 x N/2 as shown in the above diagram, but in Strassen’s
method, the four sub-matrices of result are calculated using following formulae.
Matrix Multiplication Problem
Time Complexity of Strassen’s Method
• Addition and Subtraction of two matrices takes O(N2) time. So time complexity
can be written as
T(N) = 7T(N/2) + O(N2)
• From Master's Theorem, time complexity of above method is O(NLog7) which is
approximately O(N2.8074)
• A polygon P is convex if for every pair of points x and y in P, the line xy is also in
P; otherwise, it is called concave.
P x y P x y
concave convex
The convex hull problem
concave polygon: convex polygon:
• The convex hull of a set of planar points is the smallest convex polygon
containing all of the points.
153
Graham’s Scan
• Graham's scan is a method of finding the convex hull of a finite set of points in
the plane with time complexity O(n log n).
• It is named after Ronald Graham, who published the original algorithm in 1972.
• The algorithm finds all vertices of the convex hull ordered along its boundary.
• Start at point guaranteed to be on the hull. (the point with the minimum y value)
• Sort remaining points by polar angles of vertices relative to the first point.
• Go through sorted points, keeping vertices of points that have left turns and
dropping points that have right turns.
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Scan
Graham’s Runtime
• Graham’s scan is O(n log n) due to initial sort of
angles.
A more detailed algorithm
Convex Hull by Divide-and-Conquer
• First, sort all points by their x coordinate.
– ( O(n log n) time)
• Then divide and conquer:
– Find the convex hull of the left half of points.
– Find the convex hull of the right half of points.
– Merge the two hulls into one.
5