Download as pdf or txt
Download as pdf or txt
You are on page 1of 3

3

L ECTURE 2 REVIEW. Last time: Abstract Data Types: specication versus implementation Math background: proofs by induction (particularly useful for proving recursive programs correct)
PROOF BY INDUCTION. N Illustrating proof by induction technique by an example: i=1 i. k k(k+1) Let STMT(k) denote the statement i=1 i = 2 We wish to prove that STMT(k) is true for all k 0. Easy to prove for specic values of k (e.g., k = 0, k = 1, etc.) using simple algebra. The method of induction: Explicitly show STMT(k) is true for small values of k (base case) Assume STMT(k) is true for all values of k n (induction hypothesis), and use these to show STMT(n + 1) is true as well It then follows that STMT(k) is true for all n Another example: the Fibonacci numbers: Fo F1 Fi = = = 1 1 Fi1 + Fi2 for i 2

5 Prove that Fi < ( 3 )i , for all i 1 BASE: Qn: How many base cases are we likely to need here? 2, since the denition of Fi contains two earlier terms.1 1) F1 = 1 < 5/3 2) F2 = 2 < (5/3)2 INDUCTION step: Assume true for i = 1, 2, . . . , k Need to prove Fk+1 < ( 5 )k+1 . 3

Fk + Fk1 5 5 < ( )k + ( )k1 3 3 5 k1 5 ( + 1) = ( ) 3 3 5 k1 8 = ( ) ( ) 3 3 5 k1 24 = ( ) ( ) 3 9 5 k1 25 < ( ) ( ) 3 9 5 k1 5 2 = ( ) ( ) 3 3 5 k+1 = ( ) 3 Sec 1.3: RECURSION. Natural to implement Fn recursively, since its inductively dened. A natural parallel to induction: a base case, and a recursive step. int fib (int n){ if (n <= 1) return 1; return fib (n-1) + fib (n-2); } Well see that this is not the most efcient implementation involves much re-computation. Better: retain previouslycomputed values. Best: a non-recursive formula for fib(n): 1 1 + 5 n+1 1 5 n+1 Fn = 2 2 5
1. What if we had a function G0 = G1 = G2 = 1 and Gi = Gi1 + Gi3 ?

Fk+1

(Write a program and time the three approaches for selected values of n.)

Solving recurrences Solving the Fibonacci recurrence to come up with a closed-form solution is non-trivial (need to use the technique of determining a characteristic polynomial, etc.) Not within the scope of this course... But sometimes, can solve by careful examination. An example: f1 fn = = a b + fn1 , for all n > 1

(Example: a = 5; b = 3.) Find a closed-form expression for fn . Unrolling the recursion to guess a solution (here, fn = a + b (n 1)) Proving this solution using induction Try this example on your own: f1 fn Another ADT example Maintain a collection of oating-point numbers (doubles). Operations are void create( ) Create a new object void insert(double x) Insert x into the object double min() Return the smallest value inserted thus far Can implement by storing only a single value the minimum inserted thus far. (An example where specication the use of the word insert is misleading with respect to implementation.) Preconditions and postconditions Within an ADT specication, each function/ procedure/ method specication is like a contract between the author of the function and someone who invokes the method. The postconditions of the method are what the author guarantees: When the computation directed by the method is nished, the postconditions shall be met. Usually the postconditions are constraints on the value of the result returned by the method. For instance, the postcondition of the fib(int n) method is that the value returned is the nthth Fibonacci number. The preconditions are the guarantees that the invoker of a function makes to the author, the constraints that the arguments shall meet. For instance, it is a precondition of fib(int n) that n is a positive integer. If the invoker of a function violates its preconditions, then the contract is broken and the authors guarantee of the postconditions is void. (If n is, say, a negative integer, then the author cant very well guarantee to return the nth bonacci number.) To make it less likely that an invoker violates a precondition by mistake, it is usual to document preconditions carefully and to include occasional checks in ones programs, ensuring that the preconditions are met before starting a complicated computation. With regards to our arrays example (from the last lecture) is it specied what to do if the index of an array is out of bounds? If so, must do this e.g. in Java, throw an exception. If not (as in many earlier languages), the implementer is under no obligations to handle this situation. Another ADT example Maintain a collection of oating-point numbers (doubles). Operations are void insert(double x) void remove(double x) double average() How would we implement this? depends on the interpretation of the insert and remove operations. Specically, what do we do if inserting something already in the collection (i.e., set or bag), and what do we do if were removing something not in the collection (ag an error violation of preconditions, or simply ignore)? Bag vs set: different POSTCONDs for insert: 1) POST1: Add x to the collection 2) POST2: Add x to the collection if it is not already in it. Different semantics for remove, represented as different PRECONDs: 1) PRE1: x is in the collection = = a b n + fn1 , for all n > 1

2) PRE2: (no such constraint) 3) In both cases, the same POSTCOND; depends on set or bag. (SET: x not in the collection; BAG: One fewer instance of x in the collection) Explore some alternative interpretations: 1) Set, PRE1 2) Bag, PRE1 this is interesting!! 3) Set, PRE2 4) Bag, PRE2

Stacks and queues


Denition of stacks (LIFO) and queues (FIFO) STACK: push; pop; top of stack (usually draw vertically) QUEUE: enqueue; dequeue; front; back (usually draw horizontally, with back to the right (where enqueue occurs)) Implementation: as arrays (maximum size must be known beforehand) or as linked lists

You might also like