COMP2247 - Algorithms and Data Structures

Syllabus Software Installation Assignments Tests
Lectures and Labs
**Back to Full Menu**

Algorithm Analysis BigONotations Program Algorithm Analysis Exercise



Algorithm Analysis


In this section, we study algorithm analysis and Big O notation.

Algorithm Efficiency

The efficient use of resources is one of the characteristics that determines the quality of software, such as CPU time and memory usage.

The "goodness" of an algorithm is to measure how fast it executes.

Use seven functions to evaluate algorithm's running time (time complexity)

1. Constant Function

f(n) = c

For any n, f(n) is equal to a constant.

It doesn’t matter what the value of n is.

f(n) = 1

Example:

int [] myArray = new int[250000];

int sum = myArray[0] + myArray[5690];

2. Linear Function

f(n) = n

Given an input n, f(n) is equal to n.

Examples:

Use a single loop to process the entire array with n elements.

int sum = 0;

for (int i = 0; i < myArray.length; i++) {

     sum += myArray[i];

}

Sequential search

Find the largest value or the smallest value in the array

3. Quadratic Function

f(n) = n2

Given an input n, f(n) is equal to the product of n.

Examples:

Nested loop: inner loop is a linear function, the outer loop is a linear function, the algorithm is n * n = n2 function.

Selection sort, bubble sort, insertion sort.

Nested loop where the 1st iteration of the inner loop uses one operation, the 2nd uses 2 operations, the 3rd uses 3 operations, ….

1+2+3+… + (n-1) + n = (n(n+1)) / 2 = n2/2 + n/2

This is slightly better than the full nested loop (½ is a constant).

4. Cubic Function

f(n) = n3

Given an input n, f(n) is equal to n3.

Example:

for()
   for()
      for()

5. Exponential Function

f(n) = bn

b is the base.

n is the exponent.

f(n) = 2n

Example:

A loop starts with one operation and then doubles the number of operations with each iteration. In the nth iteration, the number of operations is 2n.

1 + 2 + 4 + 8 + … + 2n-1 = 2n - 1

6. Logarithm Function

f(n) = logb n

For some constant b > 1,

x = log bn if and only if bx = n

The most common base in CS is 2:

f(n) = log n

220 = 1,048,576

Log21048576 = 20

Example:

Binary search is very fast with logarithm function.

If we use the binary search method to search a desired key in an array of 1,048,576 elements, it takes about 20 iterations.

7. N-Log-N Function

f(n) = n log n

Example:

Quick sort's average performance belongs to this function. It is much faster than Selection Sort.

If we use the quick sort method to sort an array of 1,048,576 elements, it takes about 20 * 1,048,576 iterations.

Comparing Growth Rates

Algorithms with running time proportional to the constant or logarithm function – ideal.

Algorithms with running time proportional to the linear or N-logN function – very good.

Algorithms with running time proportional to quadratic or cubic function – less practical, but still feasible for reasonably small input sizes.

Exponential function is infeasible for all but the smallest sized inputs.

Ranking

Constant Log N N N-logN N2 N3 2N
20 Log 5000000 8N + 100 5N Log N + 500 3N2 + 20N N3 + 2N2 + 4N 230

Big O Notation

Asymptotic Notations:

Big-Oh [ O ], Big-Omega [ Ω ], Big-Theta [ Θ ]

O-notation

Two functions f(n) and g(n) are defined on all positive integers to real numbers.

f(n) = O(g(n))

if there exists a positive constant c and n0

such that (∃) 0 <= f(n) <= cg(n) for all n >= n0

Examples:

1) 8n –2 = O(n)

Let's prove 0 <= 8n - 2 <= cn

To prove, we need to find c > 0 and n0 > 0

∃ (such that) 8n – 2 <= cn

∀ (for all) n >= n0

Take n0 = 1 and c = 8, 0 <= 8n - 2 <= 8n

It is true because any real number >= 8 will work for c,

and any integer >= 1 will work for n0.

2) 5n2 – 6n = O(n2)

Let's prove 0 <= 5n2 – 6n <= cn2

Take c =5, n0 = 2, it is true for all n >= n0

3) 3n2 + 4n + 2 = O(n2)

Let's prove 0 <= 3n2 + 4n + 2 <= cn2

Take c = 4

n0 3n2 + 4n + 2 <= cn2 True or False
n0 = 1 3 * 1 + 4 * 1 + 2 = 10 <= 4 * 1 = 4 Not true
n0 = 2 3 * 4 + 4 * 2 + 2 = 22 <= 4 * 4 = 16 Not true
n0 = 3 3 * 9 + 4 * 3 + 2 = 41 <= 4 * 9 = 36 Not true
n0 = 4 3 * 16 + 4 * 4 + 2 = 66 <= 4 * 16 = 64 Not true
n0 = 5 3 * 25 + 4 * 5 + 2 = 97 <= 4 * 25 = 100 True

At this point, we proved that 3n2 + 4n + 2 = O(n2), when c = 4 and for all n >= 5.

Big O notation allows us to say that f(n) is “less than or equal to” g(n) up to a constant factor and in the asymptotic sense as n grows toward infinity.

f(n) grows at a rate that is “less than or equal to” g(n).

Using O-notation, we can describe the running time of an algorithm merely by inspecting the algorithm’s overall structure.

It is used to characterize running times and space bounds in terms of the size n.

It gives an upper bound on a function, to within a constant factor.

We use it to bound the worst-case running time of an algorithm.



Case Studies

Algorithms Performance
Running Time in Big O Notation
(Time Complexity)
In-Place
Sequential Search        O(N) Yes
Binary Search        O(LogN) Yes
Quick Sort        O(NLogN) Yes
Merge Sort        O(NLogN) No (Require additional memory)
Selection Sort        O(N2) Yes
Bubble Sort        O(N2) Yes
Insertion Sort        O(N2) Yes

Sequential Search

O(N)

In the worst case, it searches the entire array with N iterations.

Binary Search

O(LogN)

The basic step in binary search is to split the array, compare X to the middle element, and then select the half of the array in which to continue the search.

Each basic step reduces the size of the array to half the previous size.

If the array has size N, binary search will require no more than log N basic steps in the worst case.

Binary Search is very efficient. Large increases in the size of the array require very small increases in the number of basic steps, approximately:

N Log2N
8 3
32,768 15
1,048,576 20

Selection Sort

O(N2)

Outer Loop i = 1      n-1 iterations in the inner loop

Outer Loop i = 2       n-2 iterations in the inner loop

......

T(n) = 1 + 2 + 3 + … + n-1

T(n) = 1 + 2 + 3 + … + n-1 + n – n = (n(n+1))/2 – n

T(n) = O(n2)

Quick Sort

Average behavior of quick-sort: O(N LogN)

Ideal case: O(N LogN)

An array of size n is partitioned into 2 pieces of size n/2 each.

T(n) = cn + 2T(n/2)

O(N LogN)

The pivot is the key.

We want the pivot to divide the array almost equally.

Randomized quick-sort

The goal of the partition is to divide the array almost equally.

The pivot is a random element of the array.

O(N LogN)

Special Case:

Apply partition() to an array of size n requires O(n) comparisons [Move i and j at least n iterations, at most 2n iterations]

Apply quick-sort to an sorted array requires:

n + (n-1) + (n-2) + … + 1 comparisons

So, it takes O(n2) running time.