CS 415, Section 002 Sonoma State University Spring, 2022
 
Algorithm Analysis
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College

Worksheet:  Analysis of Nonrecursive Algorithms

Summary

In this lab, you will analyze the complexity of some code and experimentally test your analyses.

Preparation

Download the file analysis.tgz, and decompress it with the line

tar -xvf analysis.tgz

Upon decompression, a new directory analysis should have been created, and this directory should contain TestAnalysis.cpp, a main program, and functions (run1.cpp) ... run8.cpp)). TestAnalysis.cpp allows you to conduct experiments for the subsequent exercises. To compile this program use the line:

make TestAnalysis

The program uses command-line input.

For example, to run the code for Exercise 1 with n=100, you would type

 ./testAnalysis 1 100

Note: In this lab, a variable NUMBER_REPETITIONS is specified to repeat a segment of code NUMBER_REPETITIONS2 times. This allows reasonable timings to be compared within the accuracy of the clock.

Exercises

General Notes:

  1. In exercises 1 and 2, when you are asked to determine the Big-O, Big- Ω, or Big-Θ running times, you will need to start with a micro-analysis. In your analysis, use the following constants for the time it takes a machine to do specific operations:

  2. Again for exercises 1 and 2, once you have an expression for the time required, based on a micro-analysis, you are asked to switch to a macro-analysis to get Big-O, Big- Ω, or Big-Θ running times. Although it may be tempting to argue, "just use the highest power", in at least four cases you must give a careful mathematical argument (based on inequalities and algebra).

  3. For later exercises, when you are asked to determine Big-O, Big- Ω, or Big-Θ running times,, a micro-analysis is not needed, but you need to provide a solid justification of your conclusions.

  4. Reference: "Summation formulas" from Tripod

Exercise 1

run1.cpp
#include "loop.h"

int run1(int n) {
  
  int sum = 0;

  for (int i=0 ; i < n ; i+=2)
    sum++;

  return sum;
}

  1. What are the Big-O, Big- Ω, and Big-Θ running times of run1?
  2. Run the code with n = 10:
  3. Repeat this run several times, and observe what variation seems to occur within these timings.
  4. What (range of) values do you expect for n = 20?
  5. Verify your prediction.
  6. Try several more values of N.
  7. Compare your analysis with the actual running times. Do they agree?

Exercise 2

run2.cpp
#include "loop.h"

int run2(int n) {

  int sum = 0;
  
  for (int i=0 ; i < n ; i++)
    for (int j=0 ; j < n ; j++)
      sum++;
  
  return sum;
}
  1. What are the Big-O, Big- Ω, and Big-Θ running times of run2?
  2. Run the code with several values of n.
  3. Compare your analysis with the actual running times. Do they agree?

Exercise 3

run3.cpp
#include "loop.h"

int run3(int n) {

  int sum = 0;

  for (int i=0 ; i < n ; i++)
    sum++;
  for (int j=0 ; j < n ; j++)
    sum++;
  
  return sum;
}
  1. What value will result from n = 10? n = 20?
  2. What are the Big-O, Big- Ω, and Big-Θ running times of run3?
  3. Run the code with a several values of N.
  4. Compare your analysis with the actual running times. Do they agree?

Exercise 4

run4.cpp
#include "loop.h"

int run4(int n) {

  int sum = 0;

  for (int i=0 ; i < n ; i++)
    for (int j=0 ; j < n * n ; j++)
      sum++;

  return sum;
}
  1. What are the Big-O, Big- Ω, and Big-Θ running times of run4?
  2. Run the code with several values of N.
  3. Compare your analysis with the actual running times. Do they agree?

Exercise 5

run5.cpp
#include "loop.h"

int run5(int n) {

  int sum = 0;

  for (int i=0 ; i < n ; i++)
    for (int j=0 ; j < i ; j++)
      sum++;

  return sum;
}
  1. What value will result from n = 4? n = 5?
  2. Can you recall the closed-form for the value that will be returned?
  3. What are the Big-O, Big- Ω, and Big-Θ running times of run5?
  4. If you wish, you may run the algorithm for several values of N and compare your analysis with the actual running times.

Exercise 6

run6.cpp
#include "loop.h"

int run6(int n) {

    int sum = 0;

    for (int i=0 ; i < n ; i++)
      for (int j=0 ; j < n * n ; j++)
        for (int k=0 ; k < j ; k++)
          sum++;

    return sum;
  }
  1. A closed form analysis of run6 is still possible, using the same formula as used in Exercise 5.b. Hazard a guess as to the formula and predict the result for n = 3 and n = 4.
  2. Test your predictions.
  3. Based on your formula, or your observations from the code, what are the Big-O, Big- Ω, and Big-Θ running times of run6?
  4. Run the algorithm for a few more values of N and compare your analysis with the actual running times.

Exercise 7

run7.cpp
#include "loop.h"

int run7(int n) {

   int sum = 0;

   for (int i=1 ; i < n ; i = i * 2 )
     sum++;
   
   return sum;
 }
  1. What value will result from n = 4? n = 8? n = 16
  2. What are the Big-O, Big- Ω, and Big-Θ running times of run7?
  3. Run the algorithm for a few values of n and compare your analysis with the actual running times.

Exercise 8

run8.cpp
#include "loop.h"

int run8(int n) {

  int sum = 0;

  for (int i=1 ; i <= n ; i++)
    for (int j=1 ; j <= i * i ; j++)
      if ( j % i == 0)
        for (int k=0; k < j ; k++ )
          sum++;

  return sum;
}
  1. What are the Big-O, Big- Ω, and Big-Θ running times of run8
  2. Run the code with several values of n.
  3. Compare your analysis with the actual running times. Do they agree?
  4. Given the results from b, what would you say the running time seems closer to?
  5. What is it about the innermost loop that causes the actual results to differ widely from the Big-O?
created December 21, 2021
revised December-January 2021
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.