Insertionsort
Insertionsort
STRACT
These
notes
discuss,
briefly,
topics
listed in
MU syl-
labus of
course
CSC402.
Analy-
sis of
Algo-
rithms
CSC402
ANALYSIS OF ALGORITHMS
Sunil Sitaram Shelke, Prof. Suhas Lawand
Page |1
• Why do all this? Later we will be interested mostly in runtime and space complexity of any algorithm which solves a
particular given problem. We will see soon that time complexity surely depends on size of a particular input in-
stance and it’s structure also. So we can write unambiguously about time and space requirements dependent on
instance. Moreover, a mathematical description of an input instance gives us more clear idea of how instance looks
like and how can we go about processing it for an answer.
• Basically, a problem, formally, is a set of all possible input instances. But, how to represent an instance? Does it
even matter if we represent an instance in binary or hexadecimal or some other fancy or cryptic symbol system?
• Why should we worry about binary representation? We need not, actually, theoretically. But do we really have a
device which understands things in decimal representation? Electronic computers work in binary so they do not
understand decimal. Also, any algorithm which solves prime checking problem will spend time in reading input in-
stance and will read it multiple times, probably, to solve it correctly. Naturally, time taken by algorithm will be de-
pendent on time taken to read input instance, which depends on size of an instance which in turn depends on rep-
resentation of instance. For eg. time to read binary is more than time to read same number in decimal as there are
less spaces required in decimal.
• Consider Example2 above of sorting. An example instance given above = , , ,4, −, −, , can be
written in binary as = , , , , , , , .. Notice that −, − are repre-
sented in s complement.
• So, time taken by an algorithm will be dependent on size of an input instance and that size depends on how in-
stance is represented. So, which representation should we choose? The answer is that representation will not mat-
ter as long as different representations are only constantly different from each other. Means, size of an instance
in one representation is only constantly different from size of the same instance in other representation. For eg, it
takes log10 places to represent integer . But requires log places in binary. log log10 = log = .
• We will not discuss technical reasons why above arguments about independence from actual representation. This
is a subject matter of Theory of Computation where these things are discussed in detail to establish theory of
computational complexity. So, size of an input instance is generally, traditionally represented by a parameter .
Notice that this single parameter talks about total size of instance in 1 single number.
• But wait. Consider problem of adding two matrices × and × , for some and i.e adding two matrices having
p rows and q columns. Consider it takes bits to store a single number. So, total input instance size will be =
of both matrices combined together. Generally, we see that number of operations to solve this problem is
given as . So, we generally see it as time requirement of matrix addition algorithm as , = . This be-
comes parameter time equation. This does not look like .
• So why this change? Point is that we maintain that time complexity is a function of input size but when we want get
just an estimate of time requirement then we may relax a bit and calculate time in terms of important parameters
about instance, ignoring everything else. So, as in example above we may relax and write time requirement as
, as an estimate instead of as an exact equation. So we are allowed to slightly misuse/abuse con-
cept of size of input instance, as long as we are not abusing/misusing too much. Difference between time
requirement calculation after abusing/misusing/relaxing concept of size must be only constantly different
from exact time requirement.
• Another example of such relaxation is seen in sorting. If one integer requires some constant bits and we have
size array of such numbers then total size of an instance is = , because we have already used for number
of elements in array. So we should be writing time requirement equation of any sorting algorithm as a function of
size . But we generally see time equation as i.e as a function of =number of elements in array.
Why? Assume that we do time analysis of bubble sort and say equation is = + + . Now, if we
2
′ 3′
choose to write it as a function of exact input size then replacing = ⁄, we get = 2 + + . If you
′
see, ratio is in terms of , which is assumed to be constant. So, if algorithm requires quadratic time then after
relaxing input size, it still requires quadratic time. So, if we are interested in seeing only what kind of function
time function is or growth of time function then ignoring exact size and measuring time in terms of other
important parameters is fine too.
• So, to mention clearly, time requirement/complexity of an algorithm is a function of input instance
size or it is , , , . . if we are being relaxed and interested in estimating time in terms of a few im-
portant parameters of input instance , , , …. . Whatever we choose, it is always better to write down very
clearly which parameters are you using to do time and/or space requirement analysis.
• If someone asks, what is it that any algorithm requires, apart from input and output, what will you answer? When
someone asks, what do you mean by analysing an algorithm, what will you answer?
• Almost surely, everyone will quote time and space requirement of a proposed algorithm, as analysis of that algo-
rithm. Time and Space are universal resources required by any algorithm whatsoever. So doing time and space
analysis of an algorithm is a necessary activity. But is it true that performance analysis of an algorithm means doing
only time and space analysis?
• In general, NO. Performance analysis of an algorithm means resource requirement analysis of an algorithm, for
every important resource it uses. Below are a few examples of resources other than time and space:-
▪ In Internet routing algorithms, how much network bandwidth is required is one of the important resources to
be considered as a performance analysis exercise.
▪ In parallel computing, a parallel algorithm is run on multiple independent processors/processing units at the
same time, to reduce time, utilizing parallel architecture of system. So, naturally every processor becomes a
resource and analysis of number of processors required simultaneously is an important exercise.
▪ For a machine learning algorithm, more the data, mostly better it’s performance. Not necessarily, if it’s a bad
algorithm. But, having a lot of data is not enough. Interesting and important is to know how much minimal
Page |3
amount of data is required for ML algorithm to learn automatically. Training data is an important resource.
Training data is called sample. Knowing minimum number of training data required to learn automatically is
an important performance analysis exercise. That is, doing sample complexity analysis of a learning algo-
rithm is another example of analysis other time and space analysis.
• Time and Space are, as said, universal resources required by any algorithm. For this course, we will focus
only on time and space analysis of an algorithm as a performance analysis exercise.
• For us computer engineering people, every algorithm will be implemented as an electronic computer program.
What if we do time analysis of that program? Program execution time is dependent on the performance of underly-
ing OS, size of executable created by the compiler and most importantly on the quality of high level source code
written by programmer. These factors change from system to system. But then program execution time analysis
gives an estimate near to real run time performance. For situations which are real time, for eq. automated trading in
markets, program execution time analysis is a must because of sensitivity to time.
• A possible drawback of documenting program execution time analysis is that in order to get the trend of time re-
quirement graph the program has to be executed on different instances of different sizes and multiple instances of
same size and characteristic. Such an analysis may be called empirical analysis, as purpose is to generate data
of execution time as a function of input size by choosing input instances carefully and running over several such
instances. We have to do curve fitting exercise/regression exercise on execution time data generated. Also, 2 dif-
ferent algorithms having really different time performance may not be separated out by such an empirical analysis.
It may happen that difference in time performance starts showing out sharply for very large input size which we
might not have considered for doing empirical analysis.
For eq. to emphasize the point, consider an algorithm A whose run-time is say = and an algorithm B
with run-time = . / . Algorithm B is asymptotically slower than algorithm A. But, B is better than A if
2.5
≤ i.e ≤ . After solving, we get B is better than A for ≤ 6 . That means a slower algo-
10
rithm B is as good or better than a faster algorithm A as long as input size does not cross 6 . For larger input size
i.e ≥ 7 , A is substantially better than B.
Suppose these time functions are hidden from us because we are doing empirical analysis and we have not fit any
curve over our execution time data plot right now. Say we run programs of both B and A for ≤ ≤ 7 , we will
see that execution time graphs of these 2 programs are not too much different from each other. To see sharp differ-
ence we have to have data points for small and large input sizes. Also, we have to make sure that our empirical
analysis is ok by making sure that systems characteristics like processor load, circuit slow down does not influence
true run time of programs on both systems.
The example is very superficial. But it gives intuition about possibility of us getting mislead by empirical
analysis if we are not careful about choosing input instance sizes, particular input instances having certain struc-
tures, to get true run-time performance,
• Hence, we go towards theoretical run-time analysis also i.e run-time analysis of algorithm. But there we have to
spend additional efforts because in theoretical analysis we really are not talking about physical time i.e we do not
talk in terms of seconds, nano seconds or physical space i.e number of bits or bytes or so. An analogy from physics
may help here.
▪ We have to choose what is meant by time and space and then theoretical unit of time and unit of
space.
▪ Before doing that we have to choose the universe in which we are going to measure time and space.
▪ The universe for us will be a mathematical model of a computer. We have to chalk down compo-
nents of our universe i.e mathematical model of a computer. Such a conceptual universe should not
be too far away from actual universe i.e an actual electronic computer. It should not be too close to
actual electronic computer also. Otherwise, why do theoretical analysis in the first place !!
▪ We have to conceptualise our theoretical model by ignoring enough of things from actual electronic
computer.
▪ Just like we have basic elements in universe, say atoms, we have to choose atoms in our mathemati-
cal model of a computer. This means we have to choose those instructions/operations which can be
considered as simple and very basic, from which complicated operations can be built, just like com-
plex physical objects are made of elementary atoms.
Lets see briefly what those things may be, so that we can start doing time and space complexity analysis of algorithms.
• Intel i7 processor has nearly individual instructions to operate with. In theoretical analysis, we want to
build a model of a computer which is not too far away. But is it really convenient and fruitful to deal with 8
types of basic steps in theoretical analysis? Not really.
• So we say that we have a few basic steps in our model. How many? That number is not that important.
Why? You look at algorithm and decide dynamically, looking at algorithm, which operation you want to call
Page |4
basic i.e atomic and which not. That way you have instruction set, just like i7. Guidelines are not to ignore
certain operations altogether and always.
• Example basic step set may be {add, subtract, multiply, divide, assignment, comparison, pointer derefer-
encing, reading an arbitrary node, pointer arithmetic, dynamic memory allocation of arbitrary size, freeing
memory, referencing a random array element, reallocating array, dereferencing higher dimensional point-
ers} etc.
• Just like we do not have sorting as a basic instruction in an actual processor, we should not think
of adding sorting arbitrary size array as a basic step in theoretical model too.
• Consider Intel i7 processor to be of frequency nearly 3 GHz. This means a clock cycle is of . . So, we
can consider . to be one unit of time for i7. Is it really convenient and insightful to deal with exactly this
scale of time unit? Not really.
• So, in our model we say that we have unit of time as just 1. Not 1 ns, not , not . Just . What does
that stand for? We say that time cost is added if any basic instruction/step is used by an algorithm.
Simply, we charge for every execution of every basic step used by an algorithm.
• Now, i7 may require nearly clock cycles i.e 3 units of time for multiply instruction. That means some basic
instructions in i7 require multiple units. If we want, we can add this feature in our model by saying some-
thing like algorithm costs ≥ time step cost for add basic step, instead of just . We can say ≥
time step cost for a comparison step, instead of charging just for its execution . This can be done to show
behaviour that even though basic steps are really atomic, each may not cost same. Cost is time, somehow.
• So, if we have say, for example, basic steps, theoretically, in our model of a computer, we can
have , , … , , all ≥ time costs, all different from each other. All these will potentially show in
time analysis equation. Eventually, you will not like it much, as a student. You will ask whether
tackling all these constants in time equation has given any good insight.
No matter whether you get bored of such equation, you should not ignore those constants in the first at-
tempt if you want an estimate which is not too bad. In asymptotic analysis, you will have chance to make
one approximation by setting 1 , , … , 11 to i.e assuming that all basic steps have same time cost and
that is . Furthering asymptotic analysis, you will do further approximation by dropping all constants in
equation altogether and just deal with kind of function your time equation is i.e whether it is quadratic equa-
tion, cubic equation, polynomial time equation, more than polynomial, exponential etc.
• If we do not want to do a very tight analysis of time performance then we can ignore time costs of
certain basic steps. This can be done for a few basic steps which are executed rarely or a constant num-
ber of times where of course that constant is not large. In such a case, you can ignore time cost from equa-
tion, to simplify equation. For eq. there is really no noticeable difference between = 4 + and =
4. Additional in = 4 + may be because of an assignment step that has been executed twice.
You can drop that, for convenience.
But of course there is a noticeable difference between = + + and = + ,
even for certain large values. Dropping a variable term for convenience takes you away from good esti-
mate, if your intention is to get good estimates.
But, in asymptotic analysis, there is no difference between above two equations, as we are inter-
ested in noticing only that both are quadratic equations and hence for larger and very very large values of
, both equations are not much different. Hence asymptotically 2 algorithms corresponding to above 2 time
equations are nearly as good as each other for very very large values of .
Read this entire block again, if you have confusion about time costing.
• For an algorithm, say , Decide parameters of input instance in which you want to measure time perfor-
mance. i.e you may choose to measure time as a function of input size absolutely or as seen above in case
of sorting, you may not care about exact size but measure time in terms of number of elements in array.
Decide such parameters, say , , , , ….
• Decide basic steps of algorithm. From above subsection, decide time cost of each basic step of algorithm
i.e decide whether you want to charge different time units for different steps or charge for each execution
of each basic step. Decide that.
• Finally, , , , … = ∗ , where there are say , , … , basic steps and is the
time cost per execution you decided of basic step and is the number of times step is exe-
cuted throughout algorithm execution. You will mostly set = for simplifying equation.
Page |5
• As discussed in previous sub section, once you get time equation, you may approximate that equation de-
pending on whether you are doing asymptotic analysis or not.
Lower Address
0 1 2 …
W …
Random Access Machine memory model
• Electronic computer memory comes as an array of typically 32 or 64 bit size words. We measure on lo-
cation chunk as a word. We can add this feature in theoretical model of a computer, saying one memory
location is of constant size, say, , for some constant . How large is ? Does not matter as long as it is a
constant. That saves us from fraction calculations.
• Just like von-Neumann stored program-data memory model, we call it as RAM standing for Random Ac-
cess Machine (not random access memory), which stores theoretical algorithm executable in this memory.
• Here comes a bad assumption:- We assume that no matter how large is a particular data element ac-
cessed by a basic step like add, compare etc, it takes only or a constant time cost to read that element no
matter how large it really is. We basically assume that all the individual data elements which come as a part
of input instance, are constant in size i.e each data elements either fit in word in RAM requiring size
and hence require time step cost to read OR require at most such locations in RAM requiring at most
time steps to read a data element, for some constant .
Is this really true? Does , require same amount of time as , 19 ? NO. Size of
an operand really matters to the time requirement of a basic theoretical instruction also. But lets look at
how much actual read time contributes to time complexity equation.
If in , , data elements require 1 and words in RAM. Both a and b will require 1and
time steps to read respectively, assuming word can be read in time step. If , is executed
times then total time step charge for it will 1 + × × . Whereas, if we ignore reading time then
time charge will be × . First is accurate, but only constantly different from second. This constant dif-
ference shows only constantly in final run-time equation i.e for example, using first results in cubic equation
then using second also results in a cubic equation.
If we are willing to give up on actual constants then assuming that every data element takes
only time step every time algorithm reads it. This is not really close to actual performance. But,
again, in this course we will be dealing asymptotic analysis, mostly, where not only constants but
all lower order terms in an equation are also grossly neglected.
•
Page |6
Page |7
Insertion Sort
1. Strategy Notes
2. Informal Algorithm
3. Initial Algorithm
Swap(x,y)
Insertion Sort (A, n) {
1 For = to n x=x+y; y=x-y;
2 i = k − ; // we want to fix A[k] x=x-y;
3 While i > and Ai > Ai + // Go backwards starting from current position }
4 + , ; // A[k] will move backwards through swaps, whenever required Swap(x,y)
{
5 = − ;
x=x^y; y= x^y;
Algo0 Insertion Sort
x= x^y;
}
• Swap is write intensive operation, taking 3 assignment operations. There are at least 3 ways to implement swap.
Swap(x,y)
All require 3 assignments but XOR based swap is fastest, avoiding temporary variable, in terms of number of actual
{
clock cycles required to evaluate rvalue of assignment operation. But independent of actual implementation of
temp=x; x=y;
swap, 3 assignment operations are strictly required to swap.
y= temp;
}
• If is not at its correct position in … then let, correct position of in … is say ≤ < . Algo-
rithm takes − − swaps and consequently − − assignments to get at it’s correct position in
… . Basically, algorithm literally moves element one place left whenever it finds chance to do so.
Did you notice that
either x or y will be
• Imagine that in a theatre, in a row of seats, your seat number is say and everyone from seat number 4 on- A[k] i.e swapping
wards are seated mistakenly to seat numbers less than their correct seats. You come and you first seat at seat involves element
number . To move to seat number , you are literally swapping seat with people starting with person seating at A[k] again and
and hence you are kind of sliding towards your actual seat number . Is it really required to do so? How awkward again ?
and frustrating it would be to you and everyone around?
• You can reduce amount of work by asking everyone from seat number to seat number (which they have to) to shift
to seat number more than they are right now. Once they do that, seat number is vacant and you get there by
making only move yourself.
• This reduces amount of movements quite much. But you are at seat number already. So, how can person at
seat number move to seat number ? This can be done if you get up and stand outside the row.
• Implementing these changes to above algorithm we get the following algorithm. is playing your role and …
are seat numbers.
Have you already noticed redundant assignment that may happen in some input instance? Spot out the line number and
answer in which input instance redundant assignment operation may occur. Also figure out if you can get rid of that redun-
dant operation without adding other cost to algorithm. If adjustments you suggest introduce other cost to get rid of this re-
dundant operation then adjustment will turn to be useless as overall adjustment may cancel out.
5. Example
6. Correctness
• Coming to = , algorithm tries to fix in already sorted array … − . Let position of old . in
… − be index ≤ < . Due to correctness of the algorithm, sorted position of will turn out to be +
since test condition at line 4 works on > and not on ≥.
• This proves that in sorted order comes before . Hence, algorithm is stable.
1 For = to n + +
2 currentval = Ak; −
3 i = k − ; −
4 While i > and Ai > currentval
, = count of test condition evaluated in ℎ iteration
5 + = ; − , − times test condition is TRUE in kth iteration
6 = − ; −
7 + = ; −
• Algorithm is sensitive not only to (which should be true), but also to what instance of size it is executing on. This is
seen by another variable . It basically tells, given an instance, to find correct position of ℎ element of array,
how many steps backwards were taken (and hence how many elements were copied to right by 1 position).
• There are very important operations. Given ℎ element, number of comparisons i.e search time and number
of copy to right operations done to find correct position and put it there. We may not see significance of both of
them together in above given algorithm. But, a slight modification of Insertion sort makes these operations clearly
distinct from each other.
• It is true that ≤ ≤ . Below are the reasons.
• Is it possible that = , for every ?. YES. This happens when given instance is already increasingly sorted.
So, only comparison breaks out of while loop. As a result, no element is copied place to the right to find correct
position of ℎ elements. Putting = in Equation(1.1), we get
Page |9
= + ∑ + + = 4 + − + Best
Case
(1.2)
= − , for constants = 4 + and = +
∈ Θ
Number of copy to right operations =
As seen above, becomes a linear equation in . Hence ∈ Θ. But this situation being a best case,
time spent is minimum. Hence this is the minimum time requirement for the given algorithm, given any in-
put instance. Hence,
∈ .
• Max value for ? It is = . This happens when given instance is decreasingly sorted. So, every given ℎ ele-
ment finds position of array as its correct position. As a result, − elements are copied place to the right
to find correct position of ℎ element. Putting = in Equation(1.1), we get
= + ∑ + + = + + + − + Worst
Case
(1.3)
= + − , for constants = + and = + and = +
∈ Θ
1
Number of copy to right operations =
− = =
• As seen above, becomes a quadratic equation in . Hence ∈ Θ . But this situation being a
worst case, time spent is maximum. Hence this is the maximum time requirement for the given algorithm,
given any input instance. Hence
∈
• As seen from the algorithm, extra memory places are required to maintain algorithm’s control variables and main-
taining current ℎ element in currentval. Assuming, every data element requires a constant amount of
memory, say ≤ number of bytes, for some constant , algorithms requires ≤ ∈ Θ bytes, independent
of size of the input i.e and instance characteristic (no matter whether it is best case i/p or worst case i/p).
• Hence, ∈ Ο , or most appropriately ∈ Θ (although is not mathematically wrong)
10. Input Instance Characteristic and Run time – Relation between Inversions and Run
time
In an array A,
• What we have analysed till now is time complexity behaviour of algorithm ALGO1 from best, worst and average a pair of indi-
case perspective. We have figured out lower and upper bounds independent of any given input instance. Given an Ces (i,j) is an
input instance , where of course | | = , we know | | = ∈ Ω | | = ∈ . These up- Inversion if
i<j and A[i]>A[j]
per and lower bounds are different functions. So there is no way we can bound time complexity function by Θ oper-
ator. But we know that algorithm is sensitive to input permutation i.e it takes time depending on how good/bad per-
mutation input is.
If every pair
(i,j) is an inversion
• It is natural to ask whether we can find time function | | = for algorithm, given input instance , such that
then there can be
| | ∈ . If so, we will know around exact time for a given input instance, rather than knowing just upper maximum n(n-1)/2
and lower bounds. inversions, since
there are at most
• We already know that given ℎ element , search time and hence copy to right operations depend on how n(n-1)/2 pairs (i, j)
many elements in sorted array … − are greater than and that decides time complexity function.
• In an array of size , a pair of indices , is called as an inversion, if < > i.e higher ele- Which instances
ment is at lower index. Let , be the count of inversions in given input instance . have 0 or
−
≤ , ≤ n(n-1)/2
inversions?
P a g e | 10
• In ALGO1, given input instance , for fixing element while loop of lines 4 to 6 runs exactly as many times as
many elements are greater than in array … − i.e depends on how many indices … − are in in-
version with index . Summing inversions over all values of , we get , .
• Also, line 1 executes − times. Adding this and above point, we get | | ∈ Θ − + , .
• Above time equation gives tight bound on run time, given an input instance. If is best case input instance charac-
terized by , = we get ∈ Θ − + i.e ∈ Θ. If is worst case input instance charac-
1 1
terized by , =
, we get ∈ Θ − +
i.e ∈ Θ .
Input Number of Com- Copy to Example In- How many Instances?
size= parisons(among Right Ops stance Charac-
array elements)
teristic
BEST Ω − Increasingly Exactly instance requires
Case Sorted Maximum time. But > in-
stances have time function ∈
Ω. For eg. increasingly
sorted but just first ele-
ments swapped.
WORST Ο − Decreasingly Exactly instance requires
( )= ( )
Case Sorted Maximum time. But > in-
− stances have time function ∈
=
Ο. For eg. same as in best
case explanation.
In- Θ + , − + , , --- ---
stance
• How would binary search affect number of comparisons? Will there be any change in asymptotic time complexity of
insertion sort using binary search?
• Consider fixing . ALGO1 requires worst case Ο comparisons due to linear search. Above algorithm would O(log n!)=O(n log n)
require worst case Οlog comparisons to find correct position of .
• Summing search time in the worst case of line 2 in above algorithm, over ≤ ≤ , we get worst case search
comparisons Οlog = Οlog ! = Ο log .
• Hence, it is sure that ALGO3 is better than ALGO1 in terms of number of comparisons in worst case.
• But what about copy 1 place to right assignment operations? That remains same in both the algorithms no matter
whether it is the best case input instance or worst case input instance. So, in worst case run time is still Ο due
1
to number of inversions. So asymptotic time complexity of ALGO3 is same as = Ο .
P a g e | 11
• The worst case for ALGO1 remains worst case for ALGO2 and worst case asymptotic run time is hence
= .
• What about best case of ALGO1 given as input to ALGO2? This time increasingly sorted array input is not best
case input for ALGO2. Lets see why.
To find correct position of in … − , ALGO1 requires comparison in best case because − <
so linear search terminates with 1 comparison. But ALGO2 requires log − comparisons before finding out
that − < . This is so because binary search starts from middle index always. So in case input is already
increasingly sorted then for ALGO2 Θ log − = log! = Θ log comparisons and hence =
Θ log . Hence, increasingly sorted input DOES NOT result into same asymptotic time complexity for
binary insertion sort.
• So what is the best case time complexity of binary insertion sort? There are 2 components. Search time and num-
ber of inversions. Best case instance should be the one which minimizes both together. But there is a slight prob-
lem here. To search correct position of ,when will comparisons be reduced to minimum i,e 1 or 2 or some con-
11
stant? This happens if [ ] < i.e correct position is almost the middle index. So search terminates with
Θ comparisons. But this means nearly half the elements need to move 1 place to right because they are greater
than i.e there are nearly copy to 1 place right assignments. Summing over all ≤ ≤ we get
Θ ( + Θ () ) = Θ − + Θ = Θ . That’s as bad as worst case asymptotically. This happens be-
cause of large number of inversion present in input.
• So lets see when can we have minimized inversions. This happens only when input is already sorted. But we have
already seen that run time in this case is = Θ log .
• So clearly we can not have best case input which minimizes both, number of comparisons and number of inver-
sions. Why? If an input has minimum i.e Θ comparisons (not necessarily 1 or 2) resulting out of binary search. That
means correct position of is nearly middle position of … − . This means, as seen above, nearly shifts
are required, resulting in total run time of Θ . And if an input has minimum i.e 0 or Θ inversions then it means
correct position of is near to the end of … − . As a result, binary search would require Οlog − i.e
high comparisons to reach to such an index. Clearly, we can not have any input array where we have Θ compar-
isons and Θ inversions simultaneously.
• Considering above discussion, we can figure out that best case running time of ALGO2 belongs to Θ log .
We can summarize ALGO1 and ALGO2 behaviour in below table,
Best Case Worst Case Minimum Maximum Min number Max number Best case Worst
Asymptotic Asymptotic Number of Number of of shift right of shift right input in- case in-
Run time Run time Compari- Compari- operations operations stance put in-
sons in Best sons in Best stance
case case
Linear Ω Ο − − − Increasingly Decreas-
search Happens in sorted array ingly
Inser- Happens in Happens in best case i/p Happens in sorted ar-
tion best case i/p worst case i/p worst case i/p ray
Sort
Binary Ωn log Ο − log Such case is Increasingly Decreas-
Insertio Such an i/p is Such an i/p is Such case is worst case i/p sorted array ingly
sort worst case i/p best case i/p best case i/p sorted ar-
ray
In a nutshell, we can say that as input instances are nearly as worst then ALGO2 is definitely better (not asymptotically
better) than ALGO1 since number of comparisons are bound to Ο log in ALGO2. Also, if in certain situations cost of a
comparison is greater than cost of a copy right assignment then ALGO2 has an upper hand. This may happen when array
elements are not Θ size, as assumed throughout this whole document. If elements are of variable size then a single
comparison itself take time proportional to element size. In such a case, comparisons should be avoided as much as pos-
sible. But it all depends on how variable size element collection is handled either as an array or using some other data
structure.
10 + = ;
Algo3 Insertion Sort with Block copy right
• Is there any difference in asymptotic time complexity or even in exact number of steps required compared to
ALGO1? NO. As an algorithm, ALGO3 is exactly as efficient as ALGO1.
• ALGO3 turns out to be slightly more efficient as a computer program than ALGO1 implemented as a program. This
happens only if programming language has efficient low level functions to do block memory copy. If such a facility
is available then while loop of line 8 and 9 can be converted to a single efficient programming language statement.
• Example:- memmove() function in C/C++
1 For = to n + +
2 currentval = Ak; −
3 i = k − ; −
4 While i > and >
5 + = ; −
6 = − ; −
7 + = ; −
ANSWER:-
• As in Equation(1.1), analysis goes same way. Difference lies in costing of line 4, as shown above.
• Since array elements don’t have constant size, a comparison of array elements is not Θ, as assumed pre-
viously in Algo1. Even if may be fixed, if it is too large then comparing two sized elements can not be con-
sidered to be Θ time operation.
• Hence, a comparison of two Θ size elements takes Θ time. This has been reflected in cost of line 4
above.
= + + + − + + −
• We can use Best and Worst case analysis done to Equation 1.1 as it is with cost of line 4 modified as given.
= + ∑ + + = 4 + − + Best
Case
= − , for constant = + and after dropping constant 4 and
recognizing that ∈
∈ Ω
∈ Ο
• above algorithm.
Thtrhgrrt
P a g e | 13