Download presentation
Presentation is loading. Please wait.
1
CSc212AB Data Structures Lecture 17
M. P. Johnson City College of New York, Spring, 2005 Presentation copyright 1997, Addison Wesley Longman For use with Data Structures and Other Objects Using C++ by Michael Main and Walter Savitch. Some artwork in the presentation is used with permission from Presentation Task Force (copyright New Vision Technologies Inc.) and Corel Gallery Clipart Catalog (copyright Corel Corporation, 3G Graphics Inc., Archive Arts, Cartesia Software, Image Club Graphics Inc., One Mile Up Inc., TechPool Studios, Totem Graphics Inc.). Students and instructors who use Data Structures and Other Objects Using C++ are welcome to use this presentation however they see fit, so long as this copyright notice remains intact. 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
2
M.P. Johnson, DS, CCNY, Spring 2005
Agenda Stacks Queues Recursion Hw4 up soon… 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
3
M.P. Johnson, DS, CCNY, Spring 2005
New topic: Stacks Df: ordered seq whose access is limited to FILO – LIFO Simpler than list / list w/ limitation But hugely important 2nd after array Pops up all the time Idea: each item stands on prev Each item removed is the oldest 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
4
Stacks and the STL stack
Definition A stack is a data structure of ordered entries such that entries can be inserted and removed at only one end (call the top) LIFO A stack is a Last-In/First-Out data structure. Entries are taken out of the stack in the reverse order of their insertion C push in : CHAD pop out : 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
5
M.P. Johnson, DS, CCNY, Spring 2005
Stack ops - LL Push onto, pop off Lunch room trays Maybe also: top – look, don’t remove Can “back” with LL or array LL: void stack::push(const dtype &val) { list_head_insert(val); } dtype stack::pop() { dtype val = head->data(); list_head_remove(); } 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
6
M.P. Johnson, DS, CCNY, Spring 2005
Stack ops - array Barring overflow, very fast Have data[capacity] void stack::push(const dtype &val) { data[top++] = o; } void stack::push(const dtype &val) { return data[--top]; } 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
7
M.P. Johnson, DS, CCNY, Spring 2005
Stack apps Implementation pretty simple Just a restricted sequence Lots of important apps Simple one: balancing symbols Exprs in formal langs must be valid, i.e., parseable Html – W3C Alg expressions C++ code One simple rule: []s, () can’t cross Okay: [()], ([]), not: ()(, )()(, [(]) How to check? 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
8
Stack app 1: Balancing symbols alg
Start with empty stack For each char if opening sym, push if closing sym, pop error if empty Error if not matching If get through w/o errors, then ok Draw runs for egs Complx for n = #chars? 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
9
Stack app 2: parsing infix
2*3+4*5 = ? Normally interp as (2*3) + (4*5) = 26 Win calc Standard interps as ((2*3) + 4) * 5 = 50 Win calc sci doesn’t w/o parens, “infix” notation is ambig Either way, Hard to parse Might get op long before second operand Have to remember op, retrieve when right MR, MC? Give eg 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
10
M.P. Johnson, DS, CCNY, Spring 2005
postfix How to compute 2*3 + 4*5 with wincalcstd, conserving vars? compute a1 = 2 * * compute a2 = 4 * * compute a1 = a1+a2 a1 a2 * Can write as: 2 3 * 4 5 * + “Postfix” notation or “reverse Polish”` “Polish” is “prefix”: + 2 3 Jan Lukasiewicz 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
11
M.P. Johnson, DS, CCNY, Spring 2005
Parsing postfix Parsing postfix much easier No ambig Simple alg: Walk through expr See num push See (bin) opp pop twice, apply op, push When done, pop for result That’s all! Eg: *+3+/ 8 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
12
M.P. Johnson, DS, CCNY, Spring 2005
Stack v. Queue Sequence of items Queue: FIFO enQ/deQ Stack: LIFO push/pop List usually implemented as either array Linked list Depending on freq of searchs v mods 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
13
Stack app 3: Infix Postfix
No one writes in postfix, so where’s it come from? Must convert from postfix With a stack A bit more diff than parsing postfix, but not too bad 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
14
M.P. Johnson, DS, CCNY, Spring 2005
Infix Postfix rules Read operand print operand Read ( just push Read ) pop, print all until first ( Parens not printed Don’t pop ( in any other case Read +* pop stack until op w/ lwr prior ( counts as lowest prior 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
15
M.P. Johnson, DS, CCNY, Spring 2005
Infix Postfix eg A + b*c A * b + c A * (b+c) A+b*c+(d*e+f)*g A b c * + d e * f + g * + 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
16
M.P. Johnson, DS, CCNY, Spring 2005
Function calls In prog langs, often talk about heap and stack Heap = dynamic memory Stack = other Stack mainly fills up through recursion each ftn has locals in registers Call another ftn has own Before overwriting regs, must save backups Write down on activation card (stack frame), push to stack Later, pop and write back Ftn call = (, return = ) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
17
M.P. Johnson, DS, CCNY, Spring 2005
New topic: Queues Opposite of stack FIFO/LILO “queuing” in line “calls answered in order received” Less important to DS&A per se “queuing theory” Predicting wait times at DisneyWorld Servers Print queues Web response queues Comes up in graph theory Priority queues/heaps are extension 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
18
Queues and the STL queue
Definition A queue is a data structure of ordered entries such that entries can only be inserted at one end (called the rear) and removed at the other end (call the front) – and the entry at the front of the queue is called the first entry FIFO A queue is a First-In/First-Out data structure. Entries are taken out of the queue in the same order that they were put into the queue DAHC put in : CHAD take out : CHAD 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
19
M.P. Johnson, DS, CCNY, Spring 2005
Queue ops - LL Again 2 choices: arrays & linked lists LLs: obvious: only two ops: void queue::enqueue(const dtype &val) { list_insert(tail,val); } dtype queue::dequeue() { dtype val = head->data(); list_head_remove(); return val; } 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
20
M.P. Johnson, DS, CCNY, Spring 2005
Queue ops - array Arrays: much less so How to insert? Linear time? Idea: save front and back indices and length num – “circular array” Front and back both start to end of array 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
21
M.P. Johnson, DS, CCNY, Spring 2005
Implementing queues Enqueue: A[++back] = o; Dequeue: ret A[front++]; GC: set to null Probs: Back goes off left side Front goes off right side PacMan solution init: [f][][][][b] Eg: enq 1-5: [1,f][2][3][4][5,b] Deq twice [][][3,f][4][5,b] Enq 6,7 [6][7,b][3,f][4][5] Deq 3times [6,f][7,b][][][] Deq again [][7,b,f][][][] Enq 8 [][7,f][8,b][][] Deq twice [][][b][f][] empty 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
22
M.P. Johnson, DS, CCNY, Spring 2005
DSs in C++ STL vector list: doubly linked list stack queue dequeue See for more info 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
23
Popular interview questions
How to determine whether a LL is circular? Given a ptr to the head Given a ptr to some node in the list Hard case… 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
24
M.P. Johnson, DS, CCNY, Spring 2005
Recursion In math defs, usually there’s one thing on the left being defined, and it doesn’t appear on the right But consider fib nums: F(1) = 1, f(2) = 1, f(n) = f(n-1) + f(n-2) First two: “base cases” Can code this: Pub int fib(int n) { if (n == 1 || n == 2) return 1; ret fib(n-1) + fib(n-2); } 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
25
M.P. Johnson, DS, CCNY, Spring 2005
Fib by recurs Is this correct? Yes, can “prove” by induction Bases: 1, 2 are correct Assume correct up to n Then f_n+1 = f(n) + f(n-1) This is what happens QED 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
26
M.P. Johnson, DS, CCNY, Spring 2005
Fib by recurs But is this program good? Maybe not What’s wrong? Consider call fin(-2) inf recurs loop Also, consider time: To compute fib(10), first does f(8), f(9) To compute f(9), first does f(8) (again), f(7) Lots of duplication! 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
27
M.P. Johnson, DS, CCNY, Spring 2005
Probs w recurs In case of fib, if started below base, could never stop Another poss: get stuck in one place Pub int bad(int n) { if (n == 0) ret 0; return bad(n/3 + 1) + n-1; } What happens at bad(4)? 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
28
M.P. Johnson, DS, CCNY, Spring 2005
Recurs rules Must always reach one of the bases Each step must make progress In writing code, assume all previous steps come for free Don’t duplicate work Don’t use recurs unless you have to 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
29
M.P. Johnson, DS, CCNY, Spring 2005
Recus v. iter Q: When is recurs necessary? A: never! “Pf”: stripped out by compiler Why use? Often easier, more elegant 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
30
M.P. Johnson, DS, CCNY, Spring 2005
Iter. fib Better not to use recurs for this Int fib2(int n) { int prev1 = 1, prev2 = 1; int curr = 0; while (curr < n) { temp = prev1 + prev2; prev2 = prev1; prev1 = temp; } ret prev1; END OF MATH 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
31
Outline of This Lecture
Example1 – writing digits of a number vertically Recursive Thinking: General Form Tracing Recursive Calls using blackboard to show the concepts A Closer Look at Recursion activation record and runtime stack Example2 of Recursion “racing car” – not in the textbook using slides (provided by the authors) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
32
M.P. Johnson, DS, CCNY, Spring 2005
Recursive Thinking Chapter 9 introduces the technique of recursive programming. Recursive programming involves spotting smaller occurrences of a problem within the problem itself. This presentation gives an additional example, which is not in the book. recursive functions with linked lists can sometimes be bad programming practice because the run-time stack must grow to the length of the linked list (and iterative algorithms are usually just as easy). On the other hand, the depth of recursive tree algorithms is merely the depth of the tree (and equivalent iterative algorithms can be harder to program). Data Structures and Other Objects Using C++ 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
33
Example 2: Write Number Vertically
Task Write a non-negative integer to the screen with its decimal digits stacked vertically for example: Input 1234 Output: 1 2 3 4 Problem statement How can we write a program to do this? if 1234 is divided by 1000, then the quotient will be 1234/1000 = 1; if (1234-1*1000) = 234 is divided by 100, then the quotient will be 234/100 = 2; (234-2*100) = 34; 34/10 = 3; (34-3*10) = 4; How about 12345? It is much easier to do it in a reversed order n%10 ->the last digit n <- n/10; all the digit except the last 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
34
M.P. Johnson, DS, CCNY, Spring 2005
A possible function Write an integer number vertically void write_vertical (unsigned int number) // precondition: number >=0 // Postcondition: The digits of number have been written, stacked vertically. { assert(number>=0); do { cout << number % 10 << endl; // Write a digit number = number / 10; } while (number !=0); } First let’s use a simple while loop to try to solve this problem. We know how to get the last digit of a number by using the modulo function number%10 – this is the remainder upon dividing number by 10. Then we get the quotient by dividing the number by print the remainder until the number is zero. However the order of the digits is not want we desired – we want the number stacked in the reverse order – so the first approach is to use a stack to save the digits first, and then print the digits from the stack Input 1234 Output: 4 3 2 1 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
35
Approach 1: using a stack
Write an integer number vertically void stack_write_vertical (unsigned int number) // Postcondition: The digits of number have been written, stacked vertically. { stack<int> s; do s.push(number % 10); // push a digit in the stack number = number / 10; } while (number !=0); while (!(s.empty())) cout << s.top()<< endl; //print a digit from the stack s.pop(); } Using a stack, we need at least two while loops – in the first while loop we push the digits in a stack; in the second one, we pop the digits from the stack after printing out the top. Can we accomplish our ask by a simpler coding – yes, using recursion 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
36
Approach 2: Using Recursion
Special cases: If the number has 1 digit => just write the number Assume that we know how to write the digits of an n digit number, than how do we write the digits of an n+1 digit number? Write the first n digits for number / 10 Write the last digit number % 10 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
37
Approach 2: Using Recursion
Write an integer number vertically void recursive_write_vertical(unsigned int number) // Postcondition: The digits of number have been written, stacked vertically. { if (number < 10) cout << number << endl; // Write the one digit else // recursive_write_vertical(number/10); // Write all but the last digit cout << number % 10 << endl; // Write the last digit } Two cases: If the number only has one digit we simply print it out Otherwise we break the original task into two subtasks: First print all except the last digit, stacked vertically Then print the last digit The first subtask is a simpler instance of the same task of writing a number’s digits vertically. It’s simpler because number/10 has fewer digits This step can be implemented by making a recursive call of the original function 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
38
A Closer Look at the Recursion
Recursive Function Recursive calls Stopping (Base) cases Run-time Stack the collection of activation records is stored in the stack Activation Record - a special memory block including return location of a function call values of the formal parameters and local variables 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
39
Approach 2: Using Recursion
Write an integer number vertically void recursive_write_vertical(unsigned int number) // Postcondition: The digits of number have been written, stacked vertically. { if (number < 10) // stopping case cout << number << endl; // Write the one digit else // including recursive calls recursive_write_vertical(number/10); // Write all but the last digit cout << number % 10 << endl; // Write the last digit } Two cases: If the number only has one digit we simply print it out Otherwise we break the original task into two subtasks: First print all except the last digit, stacked vertically Then print the last digit The first subtask is a simpler instance of the same task of writing a number’s digits vertically. It’s simpler because number/10 has fewer digits This step can be implemented by making a recursive call of the original function 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
40
A Closer Look at the Recursion
Recursive Function Recursive calls Stopping (Base) cases Run-time Stack the collection of activation records is stored in the stack Activation Record - a special memory block including return location of a function call values of the formal parameters and local variables 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
41
Tracing Recursive Calls
Write an integer number vertically void recursive_write_vertical_2(unsigned int number) // Postcondition: The digits of number have been written, stacked vertically. { if (number < 10) // stopping case A cout << number << endl; // Write the one digit else // including recursive calls B recursive_write_vertical(number/10); // Write all but the last digit C cout << number % 10 << endl; // Write the last digit D } } Two key points: (1) The recursive case and the stopping case (2) Activation record The return location and one formal parameter of the calling function when a function is called – a recursive one or ordinary one (3) The running stack The collection of the activation records is stored in a stack data structure 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
42
Tracing Recursive Calls
Function stack for recursive_write_vertical_2(1234) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
43
Recursive Thinking: General Form
Recursive Calls Suppose a problem has one or more cases in which some of the subtasks are simpler versions of the original problem. These subtasks can be solved by recursive calls Stopping Cases /Base Cases A function that makes recursive calls must have one or more cases in which the entire computation is fulfilled without recursion. These cases are called stopping cases or base cases 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
44
Self-Tests and More Complicated egs
An Extension of write_vertical (page 423) handles all integers including negative ones Hints: you can have more than one recursive calls or stopping cases in your recursive function 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
45
super_write_vertical
void super_write_vertical(int number) // Postcondition: The digits of the number have been written, stacked vertically. // If number is negative, then a negative sign appears on top. // Library facilities used: iostream.h, math.h { if (number < 0) cout << '-' << endl; // print a negative sign super_write_vertical(abs(number)); // abs computes absolute value // This is Spot #1 referred to in the text. } else if (number < 10) cout << number << endl; // Write the one digit else super_write_vertical(number/10); // Write all but the last digit // This is Spot #2 referred to in the text. cout << number % 10 << endl; // Write the last digit 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
46
Tracing Recursive Calls
Function stack for super_write_vertical_2(-5678) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
47
M.P. Johnson, DS, CCNY, Spring 2005
Homework Homework Reading: Section 9.1 Self-Test: Exercises 1-4 Advanced Reading: Section 9.2 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
48
Outline of This Lecture
Recursive Thinking: General Form recursive calls and stopping cases Infinite Recursion runs forever One Level Recursion guarantees to have no infinite recursion How to Ensure No Infinite Recursion if a function has multi level recursion Inductive Reasoning about Correctness using mathematical induction principle 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
49
Recursive Thinking: General Form
Recursive Calls Suppose a problem has one or more cases in which some of the subtasks are simpler versions of the original problem. These subtasks can be solved by recursive calls Stopping Cases /Base Cases A function that makes recursive calls must have one or more cases in which the entire computation is fulfilled without recursion. These cases are called stopping cases or base cases 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
50
M.P. Johnson, DS, CCNY, Spring 2005
Infinite Recursion In all our examples, the series of recursive calls eventually reached a stopping case, i.e. a call that did not involve further recursion If every recursive call produce another recursive call, then the recursion is an infinite recursion that will, in theory, run forever. Can you write one? forever(int i) { if (i>0) forever(i+1); else forever(i-1); } 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
51
Example: power (x,n) = xn
Rules: power(3.0,2) = 3.02 = 9.0 power(4.0, 3) = 4.03 = 64.0 power(x, 0) = x0 = 1 if x != 0 x-n = 1/ xn where x<>0, n > 0 power(3.0, -2) = = 1/3.02= 1/9 0n = 0 if n > 0 invalid if n<=0 (and x == 0) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
52
ipower(x, n): Infinite Recursion
Computes powers of the form xn double ipower(double x, int n) // Library facilities used: cassert { if (x == 0) assert(n > 0); //precondition if (n >= 0) return ipower(x,n); // postcondition 1 } else return 1/ipower(x, -n); // postcondition 2 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
53
ipower(x, n): Infinite Recursion
Computes powers of the form xn double ipower(double x, int n) // Library facilities used: cassert { if (x == 0) assert(n > 0); //precondition if (n >= 0) return ipower(x,n); // need to be developed into a stopping case } else return 1/ipower(x, -n); // recursive call double product =1; for (int i = 1; i<=n; ++i) product *= x; return product; X**n = x*x* ...*x n times 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
54
power(x, n): One Level Recursion
Computes powers of the form xn double power(double x, int n) // Library facilities used: cassert { double product; // The product of x with itself n times int count; if (x == 0) assert(n > 0); if (n >= 0) // stopping case product = 1; for (count = 1; count <= n; count++) product = product * x; return product; } else // recursive call return 1/power(x, -n); When n >= 0 , no recursion at all; When n< 0 call power(x,-n), and the second argument –n is positive. With a second positive argument, our power function makes no further recursive call, so the recursion ends. This brings us to the first general technique for reasoning about recursion 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
55
M.P. Johnson, DS, CCNY, Spring 2005
One Level Recursion First general technique for reasoning about recursion: Suppose that every case is either a stopping case or it makes a recursive call that is a stopping case. Then the deepest recursive call is only one level deep, and no infinite recursion occurs. 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
56
Multi-Level Recursion
In general recursive calls don’t stop a just one level deep – a recursive call does not need to reach a stopping case immediately. In the last lecture, we have showed two examples with multiple level recursions As an example to show that there is no infinite recursion, we are going to re-write the power function – use a new function name pow 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
57
power(x, n) => pow(x,n)
Computes powers of the form xn double power(double x, int n) // Library facilities used: cassert { double product; // The product of x with itself n times int count; if (x == 0) assert(n > 0); if (n >= 0) // stopping case product = 1; for (count = 1; count <= n; count++) product = product * x; return product; } else // recursive call return 1/power(x, -n); change this into a recursive call based on the observation xn=x*xn-1 if n>0 When n >= 0 , no recursion at all; When n< 0 call power(x,-n), and the second argument –n is positive. With a second positive argument, our power function makes no further recursive call, so the recursion ends. This brings us to the first general technique for reasoning about recursion 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
58
pow (x, n): Alternate impl
Computes powers of the form xn double pow(double x, int n) // Library facilities used: cassert { if (x == 0) { // x is zero, and n should be positive assert(n > 0); return 0; } else if (n == 0) return 1; else if (n > 0) return x * pow(x, n-1); else // x is nonzero, and n is negative return 1/pow(x, -n); All of the cases: x n xn = <0 underfined = =0 underfined = > != < /x-n != = != > 0 x*xn-1 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
59
How to ensure NO Infinite Recursion
when the recursive calls go beyond one level deep You can ensure that a stopping case is eventually reached by defining a numeric quantity called variant expression - without really tracing through the execution This quantity must associate each legal recursive call to a single number, which changes for each call and eventually satisfies the condition to go to the stopping case 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
60
Variant Expression for pow
The variant expression is abs(n)+1 when n is negative and the variant expression is n when n is positive A sequence of recursion call pow(2.0, -3) has a variant expression abs(n)+1, which is 4; it makes a recursive call of pow(2.0, 3) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
61
Variant Expression for pow
The variant expression is abs(n)+1 when n is negative and the variant expression is n when n is positive A sequence of recursion call pow(2.0, 3) has a variant expression n, which is 3; it makes a recursive call of pow(2.0, 2) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
62
Variant Expression for pow
The variant expression is abs(n)+1 when n is negative and the variant expression is n when n is positive A sequence of recursion call pow(2.0, 2) has a variant expression n, which is 2; it makes a recursive call of pow(2.0, 1) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
63
Variant Expression for pow
The variant expression is abs(n)+1 when n is negative and the variant expression is n when n is positive A sequence of recursion call pow(2.0, 1) has a variant expression n, which is 1; it makes a recursive call of pow(2.0, 0) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
64
Variant Expression for pow
The variant expression is abs(n)+1 when n is negative and the variant expression is n when n is positive A sequence of recursion call pow(2.0, 0) has a variant expression n, which is 0; this is the stopping case. 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
65
Ensuring NO Infinite Recursion
It is enough to find a variant expression and a threshold with the following properties (p446): Between one call of the function and any succeeding recursive call of that function, the value of the variant expression decreases by at least some fixed amount. What is that fixed amount of pow(x,n)? If the function is called and the value of the variant expression is less than or equal to the threshold, then the function terminates without making any recursive call What is the threshold of pow(x,n) Is this general enough? NO Can the following variant expression guarantees no infinite recursion if the threshold is 0? 1/n? where n = 1, 2, 3, ... 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
66
Ensuring NO Infinite Recursion
It is enough to find a variant expression and a threshold with the following properties: Between one call of the function and any succeeding recursive call of that function, the value of the variant expression changes (decreases or increases or...) by some amount. The value of the variant expression will satisfies after finite steps the condition of one of the stopping cases, e.g it is less than or equal to or greater than the threshold, then the function terminates without making any recursive call This seems more general Can the following variant expression guarantees no infinite recursion if the threshold is 0? 1/n? where n = 1, 2, 3, ... It’s depends what kind of stopping case you might have 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
67
Reasoning about the Correctness
First show NO infinite recursion then show the following two conditions are also valid: Whenever the function makes no recursive calls, show that it meets its pre/post-condition contract (BASE STEP) Whenever the function is called, by assuming all the recursive calls it makes meet their pre-post condition contracts, show that the original call will also meet its pre/post contract (INDUCTION STEP) 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
68
pow (x, n): Alternate impl
Computes powers of the form xn double pow(double x, int n) // Library facilities used: cassert { if (x == 0) { // x is zero, and n should be positive assert(n > 0); return 0; } else if (n == 0) return 1; else if (n > 0) return x * pow(x, n-1); else // x is nonzero, and n is negative return 1/pow(x, -n); All of the cases: x n xn = <0 underfined = =0 underfined = > != < /x-n != = != > 0 x*xn-1 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
69
Summary: Reason about Recursion
First check the function always terminates (not infinite recursion) next make sure that the stopping cases work correctly finally, for each recursive case, pretending that you know the recursive calls will work correctly, use this to show that the recursive case works correctly 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
70
Reading, Exercises and Assignment
Section 9.3 Self-Test Exercises 9, 10, 11*, 12* on page 448 * optional! Assignment 5 online four recursive functions due Thursday Nov 18th before class 11/15/2018 M.P. Johnson, DS, CCNY, Spring 2005
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.