Design and Analysis of Algorithm Course File 2024
Design and Analysis of Algorithm Course File 2024
2024
Noida International University
Form No. Acad. -001
Date: 16th Jan 2024 Sem.: IV Period: Sub code: PCC-CS404P Sub Name: Design and Analysis of Algorithm
Name of the Faculty Member: Ms. Kumari Pragya
1. Did you teach this/ similar subject earlier in any class? Yes
2. Class Room Management - When you enter the class observe the following:
(a) Students should get up & pay compliments; if not teach them to do so. Reply back & tell them to sit down
(b) See that the room is well ventilated with lights & fans are properly working; if not register the complaint.
(c) See that the seating arrangement is proper. If required make changes.
(d) Ask General Welfare of the students especially hosteller regarding their mess & food.
(e) In case any particular student is found not cheerful, ask the reason & do the needful.
(f) Make the students aware of General Discipline, Dress Code, Attendance and class etiquettes.
(g) Emphasize importance of taking down notes in separate copies for different subjects, keeping in step with
the class and Establish importance of asking questions.
(h) Importance of communication in English for the professionals.
3. When you find that the students are comfortable and ready to listen, then talk on the following points:
(a) Introduce yourself i.e., Name, qualification and experience in research etc. and any other information which
may influence the students to regard you as their teacher/ guide or mentor.
(b) Introduce the subject to be taught highlighting the following:
- Course Objectives
- Course Outcomes
- Expectations from the students after attending the Course
- Evaluation Scheme, Syllabus and Books
- Course Delivery to include – Total number of Units to be taught in the semester, number of Units to be
covered up before 1st, 2nd & 3rd sessional tests, sessional test schedules, duration and course coverage in the
tests, number of assignments/ quizzes, sessional marks policy etc.
- Importance and relevance of the subject in engineering field.
- Its importance for career in the industry & likely career avenues, Need of the knowledge in human
life, at national & international level.
- Brief summary of the subject taught in previous semester (to connect the current subject with the subject
taught earlier-pre-requisites)
- Clarify doubts, if any, about the curriculum and about any other matter.
(c) Create interest amongst the students so that they will eagerly wait to attend your classes.
(d) Provide information about various co-curricular and extra-curricular activities and clubs in the college and
emphasize their importance for their overall personality development and help in placement. Also inform the
incentive schemes for their participation in such activities within the college and outside.
(e) Provide information about technical Society/ professional magazines being promoted by the department and
various Centers of Excellence in the college.
4. Give them an assignment based on pre-requisites of the course-A set of 40 questions & random/ sequence of 10
questions for each student. Collect the assignment in next class to understand the level of the class as the
stepping stone for start of the new subject.
5. Just before the end of the class, enquire if they have any comments or suggestion.
6. Submit the report to the HOD after the introductory class.
Observations/ Report
● The students must have basic knowledge of data structure and c programming to derive the Analysis of algorithms.
● The course includes the Complexities of algorithms, Dynamic programming, Spanning tree algorithms, shortest path
algorithms. Therefore, students should have knowledge about the Data structure and C from their previous studies to gain the
advance knowledge during this course.
PO1 - Engineering Knowledge: Apply knowledge of mathematics, science, engineering fundamentals, and an engineering
specialization to the solution of complex engineering problems.
PO2 - Problem analysis: Identify, formulate, review research literature and analyze complex engineering problems reaching
substantiated conclusions using first principles of mathematics, natural sciences, and engineering sciences.
PO3 -. Design/development of solutions: Design solutions for complex engineering problems and design system components or
processes that meet the specified needs with appropriate consideration for the public health and safety, and the cultural, societal, and
environmental considerations.
PO5 - Modern tool usage: Create, select, and apply appropriate techniques, resources, and modern engineering and IT tools, including
prediction and modelling, to complex engineering activities with an understanding of the limitations.
PO12 - Life-long learning: Recognize the need for, and have the preparation and ability to engage in independent and life-long learning
in the broadest context of technological change.
CLO PO1 PO2 PO3 PO4 PO5 PO6 PO7 PO8 PO9 PO10 PO11 PO12
CO1 2 1 1 - 2 - - - - - - 1
CO2 2 1 1 - 2 - - - - - - 1
CO3 2 1 1 - 2 - - - - - - 1
CO4 2 1 1 - 3 - - - - - - 1
CO5 2 1 2 - 2 - - - - - - 1
CO6 2 1 - - 1 - - - - - - 1
w.e.f.:Jan. 2024
Lecture Plan
w.e.f.:Jan.2024
Lesson Plan
7 Analysis of Small Oh, & Small Omega Asymptotic 1 02/01/2024 05/01/2024 Complete
36 Standard NP- Complete Problems and Reduction Tech 4 19/04/2024 22/04/2024 Complete
302
w.e.f.:Jan. 2024
Form No. Acad. -004
Noida International University
Department of Computer Science & Engg.
Date: Date:
w.e.f.:Jan 2024
Noida International University Form No. Acad. -005
1
22044041540 ADITYA MODI
ANANT JAIN
2 22044041552
ALI MEHDI
3 22044041546
ASHUTOSH .
4 22044041564
5
22044041574 CHIRAG SHARMA
6
22044041575 DEEPAK MALIK
Dynamic
19/04/2024 21/04/2024 08/05/2024 13/05/2024 MST
I Programming IV
1 8 10
Complete
2 8 10
Complete
3 8 8
Complete
4 8 8
Complete
5 8 7
Complete
Attendance Summary
S.No. Attendance No. of Students
1 Assignment-1 3 4 2
2 Assignment- 2 3 4 2
3 Quiz 3 4
Date: Date:
w.e.f.:Jan 2024
Noida International University
Form No. Acad. -006
UNIT -1
What is an algorithm?
For example,
Algorithm:
‘’a set of steps to accomplish or complete a task that is described precisely enough that a computer
can run it’’.
Described precisely: very difficult for a machine to know how much water, milk to be added etc. in
the above tea making algorithm.
These algorithms run on computers or computational devices. For example, GPS in our
smartphones, Google hangouts.
GPS uses shortest path algorithm. Online shopping uses cryptography which uses RSA algorithm.
Characteristics of an algorithm: -
Correctness:-
Produce an incorrect answer: Even if it fails to give correct results all the time still there is a
control on how often it gives wrong result. Eg. Rabin-Miller Primality Test (Used in
50
RSA algorithm): It doesn’t give correct answer all the time.1 out of 2 times it gives
incorrect result.
Approximation algorithm: Exact solution is not found, but near optimal solution can be
found out. (Applied to optimization problem.)
Resource usage:
Here, the time is considered to be the primary measure of efficiency. We are also concerned with how
much the respective algorithm involves the computer memory. But mostly time is the resource that is
dealt with. And the actual running time depends on a variety of backgrounds: like the speed of the
Computer, the language in which the algorithm is implemented, the compiler/interpreter, skill of the
programmers etc.
1. Memory (space)
2. Time
Performance Evaluation or Apriori Analysis. Before implementing the algorithm in a system. This is
done as follows
1. How long the algorithm takes :-will be represented as a function of the size of the
input.
2. How fast the function that characterizes the running time grows with the input size.
The algorithm with less rate of growth of running time is considered better
Algorithms are just like a technology. We all use latest and greatest processors but we need to run
implementations of good algorithms on that computer in order to properly take benefits of our money
that we spent to have the latest processor. Let’s make this example more concrete by pitting a faster
2
computer (computer A) running a sorting algorithm whose running time on n values grows like n
against a slower computer (computer B) running asorting algorithm whose running time grows like n
lg n. They eachmust sort an array of 10 million numbers. Suppose that computer A executes 10
billion instructions per second (faster than anysingle sequential computer at the time of this writing)
and computer B executes only 10 million instructions per second, so that computer A is1000 times
faster than computer B in raw computing power. To makethe difference even more dramatic,
suppose that the world’s craftiestprogrammer codes in machine language for computer A, and the
2
resulting code requires 2n instructions to sort n numbers. Suppose further that just an average
programmer writes for computer B, using a high- level language with an inefficient compiler, with
the resulting code taking 50n lg n instructions.
2
Running time grows like n . Grows in nlogn.
2
2n instruction. 50 nlogn instruction
Time taken=
So choosing a good algorithm (algorithm with slower rate of growth) as used by computer B
affects a lot.
Before going for growth of functions and asymptotic notation let us see how to analyase an
algorithm.
Let us form an algorithm for Insertion sort (which sort a sequence of numbers).The pseudo code for
the algorithm is give below.
Pseudo code:
key=A[j]-----------------------------------------------------------------C2
i=j-1------------------------------------------------------------------------C4
while i>0 & A[j]>key------------------------- C5
A[i+1]=A[i]---------------------------------------------------------------C6
i=i-1------------------------------------------------------------------------C7
A[i+1]=key----------------------------------------------------------------C8
th
Let Ci be the cost of i line. Since comment lines will not incur any cost C3=0.
C1n
C2 n-1
C3=0 n-1
C4n-1
C5 C6 ) C7
C8n-1
Best case:
Worst case:
2
Quadratic function. So in worst case insertion set grows in n .
Why we concentrate on worst-case running time?
The worst-case running time gives a guaranteed upper bound on the runningtime for any input.
For some algorithms, the worst case occurs often. For example, when searching, the worst case
often occurs when the item being searched for is not present, and searches for absent items may be
frequent.
Why not analyze the average case? Because it’s often about as bad as the worst case. Order
of growth: It is described by the highest degree term of the formula for running time. (Drop lower-
order terms. Ignore the constant coefficient in the leading term.)
2
Example: We found out that for insertion sort the worst-case running time is of the form an + bn +
c.
2 2
Drop lower-order terms. What remains is an .Ignore constant coefficient. It results in n .But we
2 2
cannot say that the worst-case running time T(n) equals n .Rather It grows like n . But it doesn’t
2 2 2
equal n .We say that the running time is Θ (n ) to capture the notion that the order of growthis n .
We usually consider one algorithm to be more efficient than another if its worst-case running
time has a smaller order of growth.
Asymptotic notation
Focus on what’s important by abstracting away low-order terms and constant factors. It is
a way to compare “sizes” of functions:
o <
2 2
Example: n /2 2n = (n ), with c1 = 1/4, c2 = 1/2, and n0 = 8.
Recurrences, Solution of Recurrences by substitution, Recursion Tree and Master Method
Recursion is a particularly powerful kind of reduction, which can be described loosely as follows:
• If the given instance of the problem is small or simple enough, just solve it.
• Otherwise, reduce the problem to one or more simpler instances of the same problem.
Recursion is generally expressed in terms of recurrences. In other words, when an algorithm calls to
itself, we can often describe its running time by a recurrence equation which describes the overall
running time of a problem of size n in terms of the running time on smaller inputs. E.g.the worst case
running time T(n) of the merge sort procedure by recurrence can be expressed as
1. SUBSTITUTION METHOD:
The substitution method comprises of 3 steps
T(n)=4T(n/2)
F(n)=4f(n/2)
F(2n)=4f(n)
2
F(n)=n
2
So, T(n) is order of n
3
Guess T(n)=O(n )
3
Assume T(k)<=ck
T(n)=4T(n/2)+n
3
<=4c(n/2) +n
3
<=cn /2+n
3 3
<=cn -(cn /2-n)
3 3
T(n)<=cn as (cn /2 –n) is always positive
3
T(n)=O(n )
3
Cn /2-n>=0
n>=1
c>=2
2
Now suppose we guess that T(n)=O(n ) which is tight upper bound
2
Assume,T(k)<=ck
2
so,we should prove that T(n)<=cn
T(n)=4T(n/2)+n
2
4c(n/2) +n
2
cn +n
2 2
So,T(n) will never be less than cn . But if we will take the assumption of T(k)=c1 k -
2
c2k, then we can find that T(n) = O(n )
2. BY ITERATIVE METHOD:
e.g. T(n)=2T(n/2)+n
2
=>2 T(n/4)+n+n
2
=> 2 [2T(n/8)+ n/4]+2n
3 3)
=>2 T(n/2 +3n
k k
After k iterations ,T(n)=2 T(n/2 )+kn--------------(1) Sub
k
problem size is 1 after n/2 =1 => k=logn So,afterlogn
iterations ,the sub-problem size will be 1.
T(n)=nT(1)+nlogn
O(nlogn)
In a recursion tree ,each node represents the cost of a single sub-problem somewhere in the set of
recursive problems invocations .we sum the cost within each level of the tree to obtain a set of per
level cost,and then we sum all the per level cost to determine the total cost of all levels of recursion .
2
Constructing a recursion tree for the recurrence T(n)=3T(n/4)+cn
2
Constructing a recursion tree for the recurrence T (n)= 3T (n=4) + cn .. Part (a) shows T (n), which
progressively expands in (b)–(d) to form the recursion tree. The fully expanded tree. The fully
expanded tree in part (d) has height log4n (it has log4n + 1 levels).
i
Sub problem size at depth i =n/4
i
Sub problem size is 1 when n/4 =1 => i=log4n
i
No. Of nodes at depth i=3
i2
Cost of each node at depth i=c (n/4 )
i i2 i 2
Cost of each level at depth i=3 c (n/4 ) = (3/16) cn
log n 2 i
T(n)= i=0 4 cn (3/16)
log n -1 2 i
T(n)= i=0 4 cn (3/16) + cost of last level
i
Cost of nodes in last level =3 T(1)
cnlog 34
log 3 4
T(n)= + c n
2
<= cn
2 log 34 2
<= cn *(16/13)+ cn => T(n)=O(n )
T(n)=aT(n/b)+f(n)
where a>=1 and b>1 are constants and f(n) is a asymptotically positive function. To
e.g. T(n)=2T(n/2)+nlogn
nd
using 2 formula
log
2 2 k
f(n)=ϴ( n log n)
1 k
=>ϴ(n log n)=nlogn =>K=1
log
2 2 1
T(n)=ϴ( n log n)
2
=>ϴ(nlog n)
if small(P)
else
otherwise then n=input size a=no. Of sub- blemsn/b= input size of the sub-problems
Merge sort
It is one of the well-known divide-and-conquer algorithm. This is a simple and very efficient
algorithm for sorting a list of numbers.
How can we apply divide-and-conquer to sorting? Here are the major elements of the Merge
Sort algorithm.
Divide: Split A down the middle into two sub-sequences, each of size roughly n/2
. Conquer: Sort each subsequence (by calling MergeSort recursively on each).
Combine: Merge the two sorted sub-sequences into a single sorted list.
The dividing process ends when we have split the sub-sequences down to a single item. A
sequence of length one is trivially sorted. The key operation where all the work is done is in the
combine stage,which merges together two sorted lists into a single sorted list. It turns out that
the merging process is quite easy to implement.
The following figure gives a high-level view of the algorithm. The “divide” phase is shown on
the left. It works top-down splitting up the list into smaller sublists. The “conquer and combine”
phases areshown on the right. They work bottom-up, merging sorted lists together into larger
sorted lists.
Merge Sort
Designing the Merge Sort algorithm top-down. We’ll assume that the procedure thatmerges two
sortedlist is available to us. We’ll implement it later. Because the algorithm is called recursively
on sublists,in addition to passing in the array itself, we will pass in two indices, which indicate
the first and lastindices of the subarray that we are to sort. The call MergeSort(A, p, r) will sort
the sub-arrayA [ p..r ] and return the sorted result in the same subarray.
Here is the overview. If r = p, then this means that there is only one element to sort, and we may
returnimmediately. Otherwise (if p < r) there are at least two elements, and we will invoke the
divide-and-conquer. We find the index q, midway between p and r, namely q = ( p + r ) / 2
(rounded down to thenearest integer). Then we split the array into subarrays A [ p..q ] and A [ q
+ 1 ..r ] . Call Merge Sort recursively to sort each subarray. Finally, we invoke a procedure
(which we have yet to write) whichmerges these two subarrays into a single sorted
array.
}}
Merging: All that is left is to describe the procedure that merges two sorted lists. Merge(A, p, q,
r)assumes that the left subarray, A [ p..q ] , and the right subarray, A [ q + 1 ..r ] , have already
been sorted.We merge these two subarrays by copying the elements to a temporary working
array called B. Forconvenience, we will assume that the array B has the same index range A,
that is, B [ p..r ] . We have to indices i and j, that point to the current elements ofeach subarray.
We move the smaller element into the next position of B (indicated by index k) andthen
increment the corresponding index (either i or j). When we run out of elements in one array,
thenwe just copy the rest of the other array into B. Finally, we copy the entire contents of B
back into A.
array B[p..r]
while (i <= q and j <= r) { // while both subarrays are nonempty if (A[i] <= A[j]) B[k+
+] = A[i++] // copy from left subarray
}
while (i <= q) B[k++] = A[i++] // copy any leftover to B
Analysis: What remains is to analyze the running time of MergeSort. First let us consider the running timeof th
Now, how do we describe the running time of the entire MergeSort algorithm? We will do this
throughthe use of a recurrence, that is, a function that is defined recursively in terms of itself.
To avoidcircularity, the recurrence for a given value of n is defined in terms of values that are
strictly smallerthan n. Finally, a recurrence has some basis values (e.g. for n = 1 ), which are
defined explicitly.
Let’s see how to apply this to MergeSort. Let T ( n ) denote the worst case running time of
MergeSort onan array of length n. For concreteness we could count whatever we like: number
of lines of pseudocode,number of comparisons, number of array accesses, since these will only
differ by a constant factor.Since all of the real work is done in the Merge procedure, we will
count the total time spent in theMerge procedure.
First observe that if we call MergeSort with a list containing a single element, then the running time is aconsta
Finally, to merge both sorted lists takes n time, by the comments made above. In conclusion
we have
T ( n ) =1 if n =
1,
2T (n/ 2) + n otherwise.
Solving the above recurrence we can see that merge sort has a time complexity of Θ (n log
n) .
QUICKSORT
Sorts in place.
Description of quicksort
Combine: No work is needed to combine the subarrays, because they are sorted in place.
• Perform the divide step by a procedure PARTITION, which returns the index q that marks
the position separating the subarrays.
QUICKSORT (A, p, r)
ifp < r
Partitioning
x A[r ]
i p –1
for j p to r –1
do if A[ j ] x
theni i+1
exchangeA[i ] A[ j ]
exchangeA[i + 1] A[r ]
returni + 1
PARTITION always selects the last element A[r ] in the subarrayA[p . . r ] as the pivot the
element around which to partition.
As the procedure executes, the array is partitioned into four regions, some of which may be
empty:
Performance of Quicksort
• If the subarrays are balanced, then Quicksort can run as fast as mergesort.
• If they are unbalanced, then Quicksort can run as slowly as insertion sort.
Worst case
= T (n 1 ) + Θ (n)
= O (n2) .
Best case
Balanced partitioning
• QuickPort’s average running time is much closer to the best case than to the worst case.
• Except that here the constants are different; we get log10 n full levels and log10/9 n levels
that are nonempty.
• As long as it’s a constant, the base of the log doesn’t matter in asymptotic notation.
• Any split of constant proportionality will yield a recursion tree of depth O (lgn).
HEAPSORT
Inplace algorithm
Running Time: O(n log n)
The (binary) heap data structure is an array object that we can view as a nearly complete
binary tree.Each node of the tree corresponds to an element of the array. The tree is completely
filled on all levels except possibly the lowest, which is filled from the left up to a point.
The root of the tree is A[1], and given the index i of a node, we can easily compute the indices
of its parent, left child, and right child:
On most computers, the LEFT procedure can compute 2i in one instruction by simply shifting
the binary representation of i left by one bit position.
Similarly, the RIGHT procedure can quickly compute 2i + 1 by shifting the binary
representation of i left by one bit position and then adding in a 1 as the low-order bit.
The PARENT procedure can compute [i/2] by shifting i right one bit position. Good
implementations of heapsort often implement these procedures as "macros" or "inline"
procedures.
In a max-heap,the max-heap property is that for every node i other than the root,
A[PARENT(i)] >= A[i] ,that is, the value of a node is at most the value of its parent.
Thus, the largest element in a max-heap is stored at the root, and the subtree rooted at a
node contains values no larger than that contained at the node itself.
A min-heap is organized in the opposite way; the min-heap property is that for every
node i other than the root, A[PARENT(i)<=A[i] ,
The height of a node in a heap is the number of edges on the longest simple downward
path from the node to a leaf and
Height of a heap of n elements which is based on a complete binary tree is O(log n).
MAX-HEAPIFY lets the value at A[i] "float down" in the max-heap so that the
subtree rooted at index i obeys the max-heap property.
MAX-HEAPIFY(A,i)
1. l LEFT(i)
2. r RIGHT(i)
4. largest l
6. Largest r
7. if largest != i
9. MAX-HEAPIFY(A,largest)
At each step, the largest of the elements A[i], A[LEFT(i)], and A[RIGHT(i)] is
determined, and its index is stored in largest. If A[i] is largest, then the subtree rooted at node
i is already a max-heap and the procedure terminates. Otherwise, one of the two children has
the largest element, and A[i ] is swapped with A[largest], which causes node i and its children
to satisfy the max-heap property. The node indexed by largest, however, now has the original
value A[i], and thus the subtree rooted at largest might violate the max-heap property.
Consequently,
Figure: The action of MAX-HEAPIFY (A, 2), where heap-size = 10. (a) The initial con-
figuration, with A [2] at node i = 2 violating the max-heap property since it is not larger than
both children. The max-heap property is restored for node 2 in (b) by exchanging A [2] with
A[4], which destroys the max-heap property for node 4. The recursive call MAX-HEAPIFY
(A,4)
now has i = 4. After swapping A[4] with A[9], as shown in (c), node 4 is fixed up, and the
recursive call MAX-HEAPIFY(A, 9) yields no further change to the data structure.
Building a heap
Build-Max-Heap(A)
1. for i [n/2] to 1
2. do MAX-HEAPIFY(A,i)
4 1 3 2 1 9 1 1 8 7
We can derive a tighter bound by observing that the time for MAX-HEAPIFY to run at a node
varies with the height of the node in the tree, and the heights of most nodes are small. Our
tighter analysis relies on the properties that an n-element heap has height [log n] and at most
h+1
[n/2 ] nodes of any height h.
The HEAPSORTAlgorithm
HEAPSORT(A)
1. BUILD MAX-HEAP(A)
2. for i=n to 2
4. MAX-HEAPIFY(A,1)
1 2 3 4 7 8 9 1 1 1
0 4 6
TheHEAPSORT procedure takes time O(n log n), since the call to BUILD-MAX- HEAP takes
time
Review of Sorting: So far we have seen a number of algorithms for sorting a list of numbers in
ascendingorder. Recall that an in-place sorting algorithm is one that uses no additional array
storage (however,we allow Quicksort to be called in-place even though they need a stack of size
O(log n) for keepingtrack of the recursion). A sorting algorithm is stable if duplicate elements
remain in the same relativeposition after sorting.
Slow Algorithms: Include BubbleSort, InsertionSort, and SelectionSort. These are all
simple
2
Θ (n )in-place sorting algorithms. BubbleSort and InsertionSort can be implemented as stable
algorithms,but SelectionSort cannot (without significant modifications).
Mergesort: Mergesort is a stable Θ(n log n) sorting algorithm. The downside is that MergeSort
isthe only algorithm of the three that requires additional array storage, implying that it is not
anin-place algorithm.
Quicksort: Widely regarded as the fastest of the fast algorithms. This algorithm is O(n log n) in
theexpected case, and O(n2) in the worst case. The probability that the algorithm takes
asymptoticallylonger (assuming that the pivot is chosen randomly) is extremely small for large
n. It is an(almost) in-place sorting algorithm but is not stable.
Heapsort: Heapsort is based on a nice data structure, called a heap, which is a fast priority
queue.Elements can be inserted into a heap in O(log n) time, and the largest item can be
extracted inO(log n) time. (It is also easy to set up a heap for extracting the smallest item.) If
you only wantto extract the k largest values, a heap can allow you to do this is O(n + k log n)
time. It is anin-place algorithm, but it is not stable.
Lower Bounds for Comparison-Based Sorting: Can we sort faster than O(n log n)
time?
We will give anargument that if the sorting algorithm is based solely on making comparisons
between the keys in thearray, then it is impossible to sort more efficiently than (n log n) time.
Such an algorithm is called acomparison-based sorting algorithm, and includes all of the
algorithms given above.Virtually all known general purpose sorting algorithms are based on
making comparisons, so this isnot a very restrictive assumption. This does not preclude the
possibility of a sorting algorithm whoseactions are determined by other types of operations, for
example, consulting the individual bits ofnumbers, performing arithmetic operations, indexing
into an array based on arithmetic operations onkeys.We will show that any comparison-based
sorting algorithm for a input sequence ha1; a2; : : : ; animust
make at least (n log n) comparisons in the worst-case. This is still a difficult task if you think
about it.It is easy to show that a problem can be solved fast (just give an algorithm). But to
show that a problemcannot be solved fast you need to reason in some way about all the possible
algorithms that might everbe written. In fact, it seems surprising that you could even hope to
prove such a thing. The catch hereis that we are limited to using comparison-based algorithms,
and there is a clean mathematical way ofcharacterizing all such algorithms.
Decision Tree Argument: In order to prove lower bounds, we need an abstract way of
modeling “any possible”comparison-based sorting algorithm, we model such algorithms in
terms of an abstract modelcalled a decision tree.In a comparison-based sorting algorithm only
comparisons between the keys are used to determinethe action of the algorithm. Let ha1;
a2; : : : ; anibe the input sequence. Given two elements, aiandaj, their relative order can only
be determined by the results of comparisons likeai<aj, ai<=aj,ai=aj, ai>=aj, and ai>aj.A
decision tree is a mathematical representation of a sorting algorithm (for a fixed value of n).
Eachnode of the decision tree represents a comparison made in the algorithm (e.g., a4 : a7), and
the twobranches represent the possible results, for example, the left subtree consists of the
remaining comparisonsmade under the assumption that a4 _ a7 and the right subtree for a4 >
a7. (Alternatively, onemight be labeled with a4 < a7 and the other with a4 _ a7.)Observe that
once we know the value of n, then the “action” of the sorting algorithm is
completelydetermined by the results of its comparisons. This action may involve moving
elements around in thearray, copying them to other locations in memory, performing various
arithmetic operations on non- keydata. But the bottom-line is that at the end of the algorithm,
the keys will be permuted in the final array in some way. Each leaf in the decision tree is
labeled with the final permutation that the algorithmgenerates after making all of its
comparisons.To make this more concrete, let us assume that n = 3, and let’s build a decision
tree for SelectionSort.Recall that the algorithm consists of two phases. The first finds the
smallest element of the entire list,and swaps it with the first element. The second finds the
smaller of the remaining two items, and swapsit with the second element. Here is the decision
tree (in outline form). The first comparison is betweena1 and a2. The possible results are:
a1 <= a2: Then a1 is the current minimum. Next we compare a1 with a3 whose results might
be either:
a1 <=a3: Then we know that a1 is the minimum overall, and the elements remain in their
originalpositions. Then we pass to phase 2 and compare a2 with a3. The possible
results are:
a2 > a3: These two are swapped and the final output is ha1; a3;
a2i.
a1 > a3: Then we know that a3 is the minimum is the overall minimum, and it is swapped
witha1. The we pass to phase 2 and compare a2 with a1 (which is now in the third
position ofthe array) yielding either:
a2 > a1: These two are swapped and the final output is ha3; a1;
a2i.
a1 > a2: Then a2 is the current minimum. Next we compare a2 with a3 whose results might
be either:
a2 <=a3: Then we know that a2 is the minimum overall. We swap a2 with a1, and then pass
to phase 2, and compare the remaining items a1 and a3. The possible results are:
a1 <=a3: Final output is ha2; a1;
a3i.
a1 > a3: These two are swapped and the final output is ha2; a3;
a1i.
a2 > a3: Then we know that a3 is the minimum is the overall minimum, and it is swapped
witha1. We pass to phase 2 and compare a2 with a1 (which is now in the third
position of thearray) yielding either:
a2 > a1: These two are swapped and the final output is ha3; a1;
a2i.
The final decision tree is shown below. Note that there are some nodes that are unreachable. For
example,in order to reach the fourth leaf from the left it must be that a1 _ a2 and a1 > a2,
which cannotboth be true. Can you explain this? (The answer is that virtually all sorting
algorithms, especiallyinefficient ones like selection sort, may make comparisons that are
redundant, in the sense that theiroutcome has already been determined by earlier comparisons.)
As you can see, converting a complexsorting algorithm like HeapSort into a decision tree for a
large value of n will be very tedious andcomplex, but I hope you are convinced by this exercise
that it can be done in a simple mechanical way.
As we have seen earlier, any binary tree of height T (n) has at most 2T(n) leaves. This means
that thissorting algorithm can distinguish between at most 2T (n) different final actions. Let’s
call this quantityA (n), for the number of different final actions the algorithm can take. Each
action can be thought of asa specific way of permuting the original input to get the sorted
output.How many possible actions must any sorting algorithm distinguish between? If the input
consists of ndistinct numbers, then those numbers could be presented in any of n! different
permutations. For eachdifferent permutation, the algorithm must “unscramble” the numbers in
an essentially different way,that is it must take a different action, implying that A(n) >= n!.
(Again, A (n) is usually not exactlyequal to n! because most algorithms contain some redundant
unreachable leaves.)
T(n) lg(n!