CS 70, Fall 2000
Assignment 6: Complexity Analysis

This assignment is due at 9 PM on Wednesday, October 11th, 2000. The assignment is a written one, and must be submitted as a single file, a README. Refer to the homework policies page for general homework guidelines.

This assignment will give you practice analyzing the running time of algorithms.

General Instructions

When answering the following questions, explain clearly why your answer is correct, and show work for significant intermediate steps of computations. For example, when analyzing the running time of a code fragment, include the running time for each individual line.

Normally, it is sufficient to provide an asymptotic (big-O) analysis. Exceptions would include where the problem statement indicates otherwise, or when you believe that constants and low-order terms have a significant impact on the answer.

The code fragments are only fragments, and they may ignore certain niceties of C++ style. Don't pick at the details. Treat them as particularly explicit pseudo-code.

Submission Mechanics

Put your solutions in a text file named README and submit this file using cs70submit. Your file must be a plain text file. Do not submit (for example) a postscript file, a Word document, or an HTML file. Represent your equations using notation similar to the following examples:

        O(N)
        O(N log N)
        O(N^2)

Problem 1

Provide a big-O analysis of the running times for the code fragments given in Weiss, problem 6.15. (Do part "a" only.) You may assume that sum was declared as:

    int sum = 0;
before each code fragment. Give your analysis in terms of the loop limit variable, n.

Problem 2

Provide a big-O analysis of the running time for the code fragment given in Weiss, problem 6.16. (Again, do only part "a".) You may assume that sum was declared as:

    int sum = 0;
before each code fragment. Give your analysis in terms of the loop limit variable, n.

Problem 3

Suppose that we define a linked list class with the following data fields.

    class Node {
        private:
            long value;
            Node *next;
    };

    class List {
        private:
            Node *head;       
    };

How long do the following operations take, as a function of the length of the list, N? You may not assume any changes in the Node or List data structures.

  1. Making a copy of the list
  2. Adding a value to the start of the list
  3. Adding a value to the end of the list
  4. Removing the first value from the list
  5. Removing the last value from the list
  6. Determining whether the list contains some value V

Problem 4

Suppose that we modify the classes from Problem 3 to store C++ strings of maximum length M characters, rather than longs. Does this affect the running of any of the operations? If so, which one(s) change, why, and what is/are the new expression(s) for the running time(s)?

Notice that each list should contain its own private copy of the strings stored in it. Lists should not share strings with other lists, or with other parts of the code.

You should assume that when a string is copied or assigned, a complete copy is made of that string. (Interestingly, this assumption is not true for all implementations of the C++ library, but we'll ignore that fact for this assignment.) You should also assume that the string type has been implemented in an efficient and effective fashion (i.e., there are no O(N^2) implementations of things that can be done in O(N) time).

Problem 5

Consider the following functions, which use the List and Node data structures from Problem 3:

    // returns the length of the list
    int List::length()
    {
        Node *current = head;
        int output = 0;

        while (current != NULL) {
            output++;
            current = current->next;
        }

        return output; 
    }

    // returns the nth value in the list
    long List::nth(int n)
    {
        if (n >= length() || n < 0)
            error("List::nth out of range position");

        Node *current = head;
        for (i = 0; i < n; i++) {
            current = current->next;
        }

        return current->value;
    }

    // prints all the values in the list
    void List::print()
    {
        for (i = 0; i < length(); i++) {
            cout << nth(i) << endl;
        }
    }

Analyze the running times of these three functions. For each function, show how it could be recoded (if possible) so as to improve its asymptotic running time, and provide an analysis of the new running time. If no improvement is possible, explain why. You are only allowed to modify the executable code; you may not modify or add any fields to the Node and List data structures.


This page is maintained by Geoff Kuenning.