Вы находитесь на странице: 1из 5

Introduction: Analysis of Algorithms

The theoretical study of computer-program performance and resource usage.

Why performance analysis?


There are many important things that should be taken care of, like functionality, correctness, programmer time, User
friendliness, modularity, security, maintainability, etc. Why to worry about performance?
The answer to this is simple, we can have all the above things only if we have performance. So performance is like currency
through which we can buy all the above things. Another reason for studying performance is – speed is fun!

Given two algorithms for a task, how do we find out which one is better?

One naive way of doing this is – implement both the algorithms and run the two programs on your computer for different
inputs and see which one takes less time. There are many problems with this approach for analysis of algorithms.
1) It might be possible that for some inputs, first algorithm performs better than the second. And for some inputs second
performs better.
2) It might also be possible that for some inputs, first algorithm perform better on one machine and the second works better on
other machine for some other inputs.

Asymptotic Analysis is the big idea that handles above issues in analyzing algorithms. In Asymptotic Analysis, we evaluate
the performance of an algorithm in terms of input size (we don’t measure the actual running time).
We calculate, how does the time (or space) taken by an algorithm increases with the input size.

For example, let us consider the search problem (searching a given item) in a sorted array. One way to search is Linear Search
(order of growth is linear) and other way is Binary Search (order of growth is logarithmic). To understand how Asymptotic
Analysis solves the above mentioned problems in analyzing algorithms, let us say we run the Linear Search on a fast computer
and Binary Search on a slow computer. For small values of input array size n, the fast computer may take less time. But, after
certain value of input array size, the Binary Search will definitely start taking less time compared to the Linear Search even
though the Binary Search is being run on a slow machine. The reason is the order of growth of Binary Search with respect to
input size logarithmic while the order of growth of Linear Search is linear. So the machine dependent constants can always be
ignored after certain values of input size.
Note: - We will discuss linear search and binary search later in the course.

Does Asymptotic Analysis always work?

Asymptotic Analysis is not perfect, but that’s the best way available for analyzing algorithms. For example, say there are two
sorting algorithms that take 1000nLogn and 2nLogn time respectively on a machine. Both of these algorithms are asymptotically
same (order of growth is nLogn). So, With Asymptotic Analysis, we can’t judge which one is better as we ignore constants in
Asymptotic Analysis.
Also, in asymptotic analysis, we always talk about input sizes larger than a constant value. It might be possible that those large
inputs are never given to your software and an algorithm which is asymptotically slower, always performs better for your
particular situation. So, you may end up choosing an algorithm that is asymptotically slower but faster for your software.

Running time
 The running time depends on the input: an already sorted sequence is easier to sort.
 Parameterize the running time by the size of the input, since short sequences are easier to sort than long ones.
 Generally, we seek upper bounds on the running time, because everybody likes a guarantee.

Kinds of analyses
Worst-case: (usually)
In the worst case analysis, we calculate upper bound on running time of an algorithm. We must know the case that causes maximum number
of operations to be executed.
T (n) =maximum time of algorithm on any input of size n.

Average-case: (sometimes)
In average case analysis, we take all possible inputs and calculate computing time for all of the inputs. Sum all the calculated values and divide the
sum by total number of inputs. We must know (or predict) distribution of cases.
•T (n) =expected time of algorithm over all inputs of size n.
•Need assumption of statistical distribution of inputs.
Best-case:
In the best case analysis, we calculate lower bound on running time of an algorithm. We must know the case that causes
minimum number of operations to be executed.

Most of the times, we do worst case analysis to analyze algorithms. In the worst analysis, we guarantee an upper bound on the
running time of an algorithm which is good information.
The average case analysis is not easy to do in most of the practical cases and it is rarely done. In the average case analysis, we
must know (or predict) the mathematical distribution of all possible inputs.
The Best Case analysis is bogus. Guaranteeing a lower bound on an algorithm doesn’t provide any information as in the worst
case, an algorithm may take years to run.

Asymptotic Notations
The main idea of asymptotic analysis is to have a measure of efficiency of algorithms that doesn’t depend on machine specific
constants, and doesn’t require algorithms to be implemented and time taken by programs to be compared. Asymptotic notations
are mathematical tools to represent time complexity of algorithms for asymptotic analysis. The following 3 asymptotic notations
are mostly used to represent time complexity of algorithms.
1) Θ Notation: The theta notation bounds a functions from above and below, so it defines exact asymptotic behavior.
A simple way to get Theta notation of an expression is to drop low order terms and ignore leading constants. For
example, consider the following expression.
3n3 + 6n2 + 6000 = Θ (n3)
Θ (g (n)) = {f (n): there exist positive constants c1, c2, and n0such that 0 ≤c1 g(n) ≤f (n) ≤c2 g(n)for all n≥n0}

Dropping lower order terms is always fine because there will always be an n0 after which Θ (n3) beats Θ (n2)
irrespective of the constants involved.
For a given function g (n), we denote Θ (g (n)) is following set of functions.
The above definition means, if f(n) is theta of g(n), then the value f(n) is always between c1*g(n) and c2*g(n) for large
values of n (n >= n0). The definition of theta also requires that f (n) must be non-negative for values of n greater than
n0.

2) Big O Notation: The Big O notation defines an upper bound of an algorithm, it bounds a function only from above.

The Big O notation is useful when we only have upper bound on time complexity of an algorithm. Many times we easily find an
upper bound by simply looking at the algorithm.
Ω (g (n)) = {f (n): there exist positive constants c and n0 such that 0 ≤ f (n) ≤ cg (n) for all n≥n0}

3) Ω Notation: Just as Big O notation provides an asymptotic upper bound on a function, Ω notation provides an asymptotic
lower bound.
Ω Notation can be useful when we have lower bound on time complexity of an algorithm. As discussed in the previous post,
the best case performance of an algorithm is generally not useful, the Omega notation is the least used notation among
all three.
For a given function g (n), we denote by Ω (g (n)) the set of functions.

Ω (g (n)) = {f (n): there exist positive constants c and n0such that 0 ≤cg (n) ≤f (n) for all n≥n0}

Insertion sort

Input: sequence 〈a1, a2… an〉of numbers.


Output: permutation 〈a'1, a'2… a’n〉 such that a'1≤a'2≤…≤a’n.
Example:
Input: 8 2 4 9 3 6
Output: 2 3 4 6 8 9

Insertion sort analysis


To insert the last element we need at most N-1 comparisons and N-1 movements.
To insert the N-1st element we need N-2 comparisons and N-2 movements.
……..
……..
To insert the 2nd element we need 1 comparison and one movement.

To sum up:
2* (1 + 2 + 3 +… N - 1) = 2 * (N - 1)* N / 2 = (N-1)*N = Θ (N2)
Best case:
The best case input is an array that is already sorted. In this case insertion sort has a linear running time (i.e., O (n)). During
each iteration, the first remaining element of the input is only compared with the right-most element of the sorted subsection of
the array.
Worst case:
The simplest worst case input is an array sorted in reverse order. The set of all worst case inputs consists of all arrays where
each element is the smallest or second-smallest of the elements before it. In these cases every iteration of the inner loop will
scan and shift the entire sorted subsection of the array before inserting the next element. This gives insertion sort a quadratic
running time (i.e., O (n2)).
Average case:
In this case, all permutations equally likely.
The average case is also quadratic, which makes insertion sort impractical for sorting large arrays.

Insertion takes linear time in best case and quadratic time in worst case. We can safely say that the time complexity of Insertion
sort is O (n2). Note that O (n2) also covers linear time.
Is insertion sort a fast sorting algorithm?
•Moderately so, for small n.
•Not at all, for large n.

Merge sort

MERGE-SORT A [1 . . . n]
1. If n= 1, done.
2. Recursively sort A [1 . . .  n / 2 ] and A [  n / 2 +1 . . . n].
3. “Merge” the 2 sorted lists.

Merging two sorted arrays:-

Time = Θ (n) to merge a total of n elements (linear time).

Analyzing merge sort

Sloppiness: Should be T  n / 2 ) + T (  n / 2 , but it turns out not to matter asymptotically.
Recurrence for merge sort:

•We shall usually omit stating the base case when T (n) = Θ (1) for sufficiently small n, but only when it has no effect on the
asymptotic solution to the recurrence.

Recursion tree
Solve T (n) = 2T (n/2) + cn, where c > 0 is constant.
Note
•Θ (nlgn) grows more slowly than Θ (n2).
•Therefore, merge sort asymptotically beats insertion sort in the worst case.
•In practice, merge sort beats insertion sort for n> 30or so.

Вам также может понравиться