Lecture 4/20: Big O and Asymptotic Analysis


April 20, 2020

đź“‚Associated files

Lecture 6: Big O and Asymptotic Analysis

CS 106B: Programming Abstractions

Spring 2020, Stanford University Computer Science Department

Lecturers: Chris Gregg and Julie Zelenski

An image showing the various graphs associated with n, log(n), n log n, n^2, n^3, and 2^n (all things we will learn about today


Slide 2

Announcements


Slide 3

Computational Complexity


Slide 4

Assembly Code for the vectorMax function

   0x000000010014adf0 <+0>:	push   %rbp
   0x000000010014adf1 <+1>:	mov    %rsp,%rbp
   0x000000010014adf4 <+4>:	sub    $0x20,%rsp
   0x000000010014adf8 <+8>:	xor    %esi,%esi
   0x000000010014adfa <+10>:	mov    %rdi,-0x8(%rbp)
   0x000000010014adfe <+14>:	mov    -0x8(%rbp),%rdi
   0x000000010014ae02 <+18>:	callq  0x10014aea0 <std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(long)+32>
   0x000000010014ae07 <+23>:	mov    (%rax),%esi
   0x000000010014ae09 <+25>:	mov    %esi,-0xc(%rbp)
   0x000000010014ae0c <+28>:	mov    -0x8(%rbp),%rdi
   0x000000010014ae10 <+32>:	callq  0x10014afb0 <std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(long)+304>
   0x000000010014ae15 <+37>:	mov    %eax,-0x10(%rbp)
   0x000000010014ae18 <+40>:	movl   $0x1,-0x14(%rbp)
   0x000000010014ae1f <+47>:	mov    -0x14(%rbp),%eax
   0x000000010014ae22 <+50>:	cmp    -0x10(%rbp),%eax
   0x000000010014ae25 <+53>:	jge    0x10014ae6c <vectorMax(Vector<int>&)+124>
   0x000000010014ae2b <+59>:	mov    -0xc(%rbp),%eax
   0x000000010014ae2e <+62>:	mov    -0x8(%rbp),%rdi
   0x000000010014ae32 <+66>:	mov    -0x14(%rbp),%esi
   0x000000010014ae35 <+69>:	mov    %eax,-0x18(%rbp)
   0x000000010014ae38 <+72>:	callq  0x10014aea0 <std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(long)+32>
   0x000000010014ae3d <+77>:	mov    -0x18(%rbp),%esi
   0x000000010014ae40 <+80>:	cmp    (%rax),%esi
   0x000000010014ae42 <+82>:	jge    0x10014ae59 <vectorMax(Vector<int>&)+105>
   0x000000010014ae48 <+88>:	mov    -0x8(%rbp),%rdi
   0x000000010014ae4c <+92>:	mov    -0x14(%rbp),%esi
   0x000000010014ae4f <+95>:	callq  0x10014aea0 <std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(long)+32>
   0x000000010014ae54 <+100>:	mov    (%rax),%esi
   0x000000010014ae56 <+102>:	mov    %esi,-0xc(%rbp)
   0x000000010014ae59 <+105>:	jmpq   0x10014ae5e <vectorMax(Vector<int>&)+110>
   0x000000010014ae5e <+110>:	mov    -0x14(%rbp),%eax
   0x000000010014ae61 <+113>:	add    $0x1,%eax
   0x000000010014ae64 <+116>:	mov    %eax,-0x14(%rbp)
   0x000000010014ae67 <+119>:	jmpq   0x10014ae1f <vectorMax(Vector<int>&)+47>
   0x000000010014ae6c <+124>:	mov    -0xc(%rbp),%eax
   0x000000010014ae6f <+127>:	add    $0x20,%rsp
   0x000000010014ae73 <+131>:	pop    %rbp
   0x000000010014ae74 <+132>:	retq

Slide 5

Algorithm Analysis: Primitive Operations


Slide 6

Algorithm Analysis: Primitive Operations

Image showing the analysis of the vectorMax function (described below)


Slide 7

Algorithm Analysis: Primitive Operations


Slide 8

Algorithm Analysis: Simplify!


Slide 9

Algorithm Analysis: Big O


Slide 10

Algorithm Analysis: Removing constants and less significant factors

5n + 2 is O(n)


Slide 11

Big O: important functions

constant logarithmic linear n log n quadratic polynomial
(other than n2, (n^2))
exponential
O(1) O(log n) O(n) O(n log n) O(n2), O(n^2) O(nk), O(n^k)
(where k >= 1)
O(an), O(a^n)

Slide 12

Algorithm Analysis: Back to vectorMax()

int vectorMax(Vector<int> &v){
    int currentMax = v[0];
    int n = v.size();
    for (int i = 1; i < n; i++){
        if (currentMax < v[i]) {
            currentMax = v[i];
        }
    }
    return currentMax;
}

Slide 13

Algorithm Analysis: Back to vectorMax()

int vectorMax(Vector<int> &v){
    int currentMax = v[0];
    int n = v.size();
    for (int i = 1; i < n; i++){
        if (currentMax < v[i]) {
            currentMax = v[i];
        }
    }
    return currentMax;
}

Slide 14

Graphing the Data for vectorMax

A graph of running time -vs- input size for vectorMax. There are two sets of data, one when the maximum is always the first value, and the other where the maximum is the last value, and at each iteration there is a new maximum. The data indicates that the relationship is linear, as the lines drawn through the data are almost perfectly straight.


Slide 15

Nested Loops


Slide 16

Plotting O(n^2) behavior

A graph of running time -vs- input size for loopTest1, which is a singly-nested loop. The graph clearly shows a parabolic increase in the amount of time as the number of elements grows.


Slide 17

Cubic O(n^3) Behavior

int nestedLoop2(int n){
    int result = 0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            for (int k = 0; k < n; k++) {
                result++;
            }
        }
    }
    return result;
}

Slide 18

Plotting O(n^2) -vs- O(n^3) behavior

A graph of running time -vs- input size for loopTest1 and loopTest2, The cubic data shows a vastly faster increasing parabolic curve than the quadratic data


Slide 19

Hidden loops

vec before insert:

index:  0   1   2   3 
value: 4 8 15 16
vec.insert(0, 100);
index:  0   1   2   3   4 
value: 100 4 8 15 16

A graph of running time -vs- input size for populateVec with inserting and with appending. The insert is clearly O(n^2) and the append is O(n)


Slide 20

Constant Time


Slide 21

Linear Search

void linearSearchVector(Vector<int>& vec, int numToFind){
    int numCompares = 0;
    bool answer = false;
    int n = vec.size();
    
    for (int i = 0; i < n; i++) {
        numCompares++;
        if (vec[i]==numToFind) {
            answer = true;
            break;
        }
    }
    cout << "Found? " << (answer ? "True" : "False") << ", "
         << "Number of compares: " << numCompares << endl << endl;
}

Slide 22

Binary Search

A bunch of random numbers


Slide 23

Binary Search

Here is some code that performs a binary search:

void binarySearchVector(Vector<int> &vec, int numToFind) {
    int low=0;
    int high=vec.size()-1;
    int mid;
    int numCompares = 0;
    bool found=false;
    while (low <= high) {
        numCompares++;
        mid = low + (high - low) / 2; // to avoid overflow
        if (vec[mid] > numToFind) {
            high = mid - 1;
        }
        else if (vec[mid] < numToFind) {
            low = mid + 1;
        }
        else {
            found = true;
            break;
        }
    }
    cout << "Found? " << (found ? "True" : "False") << ", " <<
    "Number of compares: " << numCompares << endl << endl;
}

Slide 24

Exponential Time


Slide 25

Ramifications of Big O Differences

constant logarithmic linear n log n quadratic polynomial
(other than n2, (n^2))
exponential
1 nanoseconds 10 nanoseconds 1 microsecond 10 microseconds 1 millisecond 1 second 10^292 years

Slide 26

Ramifications of Big O Differences

constant logarithmic linear n log n quadratic polynomial
(other than n2, (n^2))
exponential
1 milliseconds 10 milliseconds 1 second 10 seconds 17 minutes 277 hours heat death of the universe

Slide 27

Recap