CS 367 - Introduction to Data Structures - Section 3
Written Assignment Zero: O-Notation and Run-Time Analysis
Due Thursday, October 9, 1997 at 2:30pm
Contents
Answer the questions below clearly and succinctly. State why your answer is
so, but keep your explanation simple.
If you need help, please see Marc Dreyfuss (the TA). Marc will be
holding additional office hours during class times next week (9/30 and
10/2).
Recall the formal definition of O-notation from class: Given functions
f and g, function f is said to be O(g) if there
exist positive constants k and N such that for all n >= N, f(n) <= kg(n).
- a.
- Let f(n) = 2n3 + 47 and g(n) = (n-1)4. Find
constants k,N that demonstrate that f=O(g).
- b.
- Prove or disprove (Yikes! I know I said there won't be many
proof-type questions in this class, but I can't go the whole semester
without making you at least try a few. This is the only one on this
assignment. I promise.): If f=O(g) and g=O(h) then
f=O(h). Hint: To disprove this claim, show three specific
functions, f, g, and h for which this is not
true. To prove the claim, assume there are constants
k0,N0 that
demonstrate f=O(g) and constants
k1,N1 that demonstrate g=O(g); provide
constants k2,N2 expressed in terms of the
other constants that demonstrate that f=O(h).
- c.
- Explain why the statement, ``The running time of the algorithm A
is at least O(n2),'' is content-free. (This problem was taken
from this book.)
Fibonacci numbers are numbers in the sequence 0,1,1,2,3,5,8,13,...
The next element in the Fibonacci sequence is computed by adding the two
previous elements. Fibonacci numbers have interesting mathematical
properties and also occur in nature (for example, the arrangements of the
petals of a sunflower). For further information on Fibonacci numbers and
their history, see:
http://www.mcs.surrey.ac.uk/Personal/R.Knott/Fibonacci/fib.html.
The Fibonacci function, fib, is a function that takes a non-negative
integer n and returns the nth number in the Fibonacci
sequence. fib(n) can be specified recursively:
fib(n) =
0 if n = 0
1 if n = 1
fib(n-1) + fib(n-2) otherwise
There are multiple ways the Fibonacci function can be implemented in C++.
Two such ways are shown below. The first is recursive (like the above
definition) - the function calls itself. The second is iterative - it
uses a loop rather than recursion. More information on recursion and
recursive functions can be found on the class web site at:
http://www.cs.wisc.edu/~cs367-3/Notes/recursion.txt, as well
as in Main & Savitch (Chapter 9) and Wang (Section 3.2).
// FILE: fib-rec.C
// compute the nth Fibonacci number, recursively
unsigned fib(unsigned n)
{
unsigned f;
if (n==0)
f = 0;
else if (n==1)
f = 1;
else
f = fib(n-1) + fib(n-2);
return f;
}
// FILE: fib-iter.C
// compute the nth Fibonacci number, iteratively
unsigned fibIter(unsigned n)
{
unsigned f, f1, f2;
if (n==0)
f = 0;
else if (n==1)
f = 1;
else {
f2 = 0;
f1 = 1;
for(unsigned i=1; i< n; i++) {
f = f1 + f2;
f2 = f1;
f1 = f;
}
}
return f;
}
\noindent
(This code, as well as a program to test it, can be found on
the web at: http://www.cs.wisc.edu/~cs367-3/Programs/Fib/
.)
- a.
- What is the run-time complexity of the iterative version of the
Fibonacci function (fibIter) in terms of O-notation?
- b.
- What is the run-time complexity of the recursive version of the
Fibonacci function (fibIter) in terms of O-notation?
(Hint: consider the trace of an execution of fib -
see the notes at:
http://www.cs.wisc.edu/~cs367-3/Notes/recursion.txt for details. How many times does a fib expression occur in the trace?)
- c.
- Comment (briefly) on the relative advantages of the two different
implementations of the Fibonacci functions.
The Towers of Hanoi is a game in which you begin with three spindles (the
``towers'') - two empty and one stacked with a selected number of discs
in graduated sizes. Your object is to transfer the entire stack of discs
to one of the other two spindles. The catch? You must do it by moving only
a single disc at a time from one spindle to another, and you may never
place a larger disc on top of a smaller one.
For more information (and a chance to play), check out these web sites:
The standard strategy for winning the Towers of Hanoi game is to think
recursively. For example, if you need to move a stack of four discs from
the first spindle to the third, you can solve the smaller problem of moving
the three smallest discs to the second spindle, then move the fourth disc
to the third spindle, and then once again solve the three disc problem,
this time moving them on top of the fourth disc, on the third spindle.
This is illustrated in the following C++ code:
void move(unsigned n, unsigned A, unsigned B, unsigned C)
// n : number to move
// A : source spindle, B : destination spindle, C : spare spindle
{
if (n==1)
cout << "Move the top disc from " << A << " to " << C << "\n";
else {
move(n-1,A,B,C);
move(1,A,C,B);
move(n-1,B,C,A);
}
}
(This code, along with a main function for testing it, can be found on-line
at: http://www.cs.wisc.edu/~cs367-3/Programs/Hanoi/hanoi.C.)
- a.
- In terms of O-notation and n (the number of discs
Towers of Hanoi is played with), what is the run-time complexity of the above move
function?
- b.
- What does this say about how long it would take a person to play an
100-disc version of the game?
Thus far, we have considered two different kinds of container classes -
bags and lists. We have also considered two different representations for
these container classes. The goal of this exercise is to compare the
worst-case complexities of several member functions of bags implemented
using arrays, lists implemented using arrays, and lists implemented using
linked lists.
Consider the insert function and the equality operator. Code for the three
versions of insert is shown below:
void Bag::insert(int entry)
{
assert(!isFull());
data[used] = entry;
used++;
}
(This code, along with related code, can be found on-line at:
http://www.cs.wisc.edu/~cs367-3/Programs/Bags/.)
void List::insert(int entry)
{
assert(!isFull());
for(size_t i=used; i>0; i--)
data[i] = data[i-1];
data[0] = entry;
used++;
}
(This code, along with related code, can be found on-line at:
http://www.cs.wisc.edu/~cs367-3/Programs/Lists/Arrays/.)
void List::insert(int entry)
{
ListItem *temp;
assert(!isFull());
// special case for empty list
if (isEmpty())
list = new ListItem;
else {
temp = list;
list = new ListItem;
list->next = temp;
temp->prev = list;
}
list->val = entry;
used++;
}
(This code, along with related code, can be found on-line at:
http://www.cs.wisc.edu/~cs367-3/Programs/Lists/Linked/.)
- a.
- In terms of O-notation, what is the worst-case run-time complexity of Bag::insert?
- b.
- In terms of O-notation, what is the worst-case run-time
complexity of List::insert, where the class List is implemented with arrays?
- c.
- In terms of O-notation, what is the worst-case run-time
complexity of List::insert, where the class List is implemented with linked lists?
In class we have discussed the run-time properties of the equality operator
(as defined in class) for Bag. Suppose we define an equality operator for
lists such that two lists are said to be equal if they have the same
elements in the same order.
- d.
- Write pseudocode for an equality operator for the class List implemented with arrays.
- e.
- In terms of O-notation, what is the worst-case run-time
complexity of the equality operator for the class List, implemented with arrays?
- f.
- Write pseudocode for an equality operator for the class List
implemented with linked lists.
- g.
- In terms of O-notation, what is the worst-case run-time
complexity of the equality operator for the class List, implemented with
linked lists?
- h.
- Compare the efficiency of the equality operator for the two
list implementations as well as for the class Bag (discussed in class and
as part of Programming Assignment Zero).
Suppose a sort function is added to the List class. For the array
representation, an implementation using the selection sort algorithm might
look like this:
void List::sort()
// sorts the list using a selection sort
{
int min;
size_t k,minIndex;
for(k=0; k+1 < used; k++) {
minIndex = k;
min = data[k];
for(size_t j=k+1; j < used; j++) {
if (data[j] < min) {
min = data[j];
minIndex = j;
}
}
data[minIndex] = data[k];
data[k] = min;
}
}
- i.
- What is the run-time complexity of this algorithm, in terms of
O-notation?
- j.
- Write pseudocode for a selection sort member function for the List
class implemented with linked lists rather than arrays.
- k.
- Which of these two sort implementation is more efficient?
- l.
- Briefly discuss the relative merits of the two implementations of the
class List discussed in class in terms of run-time efficiency.
- a.
- Read about dynamic arrays in Main & Savitch (Chapter 4,
137--177). (If you have not been able to purchase a copy, use the
reserve copies available at Wendt Library.)
With dynamic arrays, (like with linked lists) container classes such as bag
and list need not have a fixed capacity. Instead of disallowing an insert
when a bag (or list) is full, we can resize the bag (or list) by creating a
larger dynamic array, copying the data, and then discarding the old array.
The following C++ function is adapted from Main & Savitch (p. 174):
void Bag::resize(size_t new_capacity)
{
int *new_array;
if (new_capacity <= capacity) // no need to create more space
return;
new_array = new int[new_capacity];
for(size_t i=0; i<used; i++)
new_array[i] = data[i];
delete[] data;
data = new_array;
capacity = new_capacity;
}
- b.
- What is the complexity (in terms of O-notation) of Bag::resize?
- c.
- Is such resizing needed for a linked-list representation of a
container class? Why or why not?
- d.
- Which representation makes more sense if the size of the container
class is likely to change frequently? Explain.
- 1.
-
Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest.
Introduction to Algorithms.
The MIT Press, 1990.
- 2.
-
Michael Main and Walter Savitch.
Data Structures and Other Objects Using C++.
Addison Wesley, 1997.
- 3.
-
Paul S. Wang.
C++ with Object-Oriented Programming.
PWS Publishing Company, 1994.
Grading
The assignment has been graded on an 100 point scale. A
grading key is now available.
For more information on general grading
policy, click
here.
Submitting
Turn in a written (hard-copy) solution at the beginning of class on the day
it is due.
Solution
Marc Dreyfuss has put together a solution
based on your own answers. This
can be contrasted with the
instructor's solution.
Late Policy
I'd like to discuss the solutions to the assignment on the day it is
due. This is only possible if assignments are not late. If you feel you
truly have a justifiable excuse for turning in the assignment late, you
must clear it with me at least one day in advance.