Download presentation
Presentation is loading. Please wait.
Published byMarian Cobb Modified over 9 years ago
1
Stacks & Recursion
2
Stack pushpop LIFO list - only top element is visible top
3
Defining the ADT "Stack" Data: – a linear collection of data items in which all operations occur at one end, called the top Basic Operations: – construct a stack (usually starts empty) – find out if stack is empty – push: add an item on top of the stack – accessing the topmost item Top: retrieve the top item of the stack Pop: remove the top item of the stack
4
Some Implementation choices fixed-size array – capacity (max # elements) decided at compile-time could be too small for expected amount of data could be too large, so space is wasted – size (current # elements used) – fast dynamic array – capacity decided at run-time – size may be less than or equal to the capacity – uses pointers linked list – size changes as needed during program execution – uses pointers
5
Implementation example myTop myArray 7654321076543210 typedef Complx StackElement; const int CAPACITY = 8; int myTop; StackElement myStack[CAPACITY]; Complx X; push(&myStack,X); initially empty (myTop is negative)
6
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved. 0-13-140909-3 6 Using the stack - 1 Model with an array – Let position 0 be top of stack Problem … consider pushing and popping – Requires much shifting
7
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved. 0-13-140909-3 7 Using the stack - 2 A better approach is to let position 0 be the bottom of the stack Thus our design will include – An array to hold the stack elements – An integer to indicate the top of the stack
8
Addressing the problem Too much or too little space Whatever size you pick, some day, there will be too much data In embedded systems, RAM is a premium Need a dynamic solution (TBD) – Size changes as needed – No waste – Slower when adding new elements
9
The "node" concept a "node" is one element of a stack more than just the data – index of next and/or previous node – trivial for array implementations each node is a struct – data may be a struct INSIDE the node struct struct node {int next; Complx data;}; node myStackNode[CAPACITY];
10
Recursion An alternative to loops
11
What is recursion? a function calls itself – direct recursion a function calls its caller – indirect recursion f f1 f2
12
Recursion-1 Alternative to iteration (looping) – often more "elegant" and concise than a loop – sometimes very inefficient – easier to program than loops Useful when – a problem can be defined in terms of similar sub-problems – eventually reach a "known" answer (base case) Inefficient if duplicate values exist
13
Head vs. Tail Recursion head recursion – requires "deepest" call to complete before any values are known – current stack state must be preserved tail recursion – compiler can "collapse" the stack
14
Head vs. Tail recursion Note: base case is ALWAYS 1st tail(3) is: 3 2 1 void tail(int n) { if(n == 0) return; else printf("tail - n=%i\n",n); tail(n-1); // } head(3) is: 2 3 void head(int n) { if(n == 1) return; else head(n-1); // printf("head - n=%i\n",n);); }
15
Caveats Static data is NOT on the "stack" – never gets re-allocated – same values for EVERY call Must have an "exit" – prevent an infinite loop
16
Outline of a Recursive Function if (answer is known) provide the answer & exit else call same function with a smaller version of the same problem base case recursive case
17
Factorial (n) - looping fact (int n) {if (n<0) exit(1); answer=1; for (i=1; i<=n; i++) answer=answer*i; // loop n times return (answer); } This is a simple problem
18
Factorial (n) – head recursive definition: Factorial (n) = n * Factorial (n-1) int Fact (int n) {if (n<0) exit(1); if (n == 0 | n==1) return 1; return n * Fact (n-1); // stack must be saved // cannot do the *'s until last value }
19
Factorial "n" (tail recursive) tail_fact (n, sofar) // set "sofar" same as "n" { if (n == 0 | n==1) return sofar; else // nothing to save on the stack // because it is in the 2 nd parameter return tail_fact (--n, sofar * n); } // here's how to run it printf ("5!=%i",tail_fact(5,5));
20
Keeping track compiler builds code to: – create a new stack pointer and stack space – put local variables & parameters on stack each "return" returns control to caller's next instruction (the inst after the call) returned value, is in caller's stack space – same as ANY function this is called "unwinding"
21
Recursive Call Tree int Fact (int n) { if (n == 0 | n==1) return 1; return n * Fact (n-1); } Fact (4) 3*Fact (2) 4*Fact (3) 2*Fact (1) 24 6 2
22
Fibonacci Series Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, …. n= 1 2 3 4 1 for n <= 2 fib(n) = fib(n-2) + fib(n-1) for n>2 for n=4: fib(2)+fib(3) 1 + 2 3
23
Tracing fib(6) 21 32 4 3 21 5 6 4 21 32 11 1 +
24
Ackermann's function A(0, n) = n + 1 A(m, 1) = A(m+1, 0) A(m+1, n+1) = A(m, A(m+1, n))
25
What Does a Compiler Do? Lexical analysis – divide a stream of characters into a stream of tokens total = cost + 0.08 * cost; if ( ( cond1 && ! cond2 ) ) Parsing – do the tokens form a valid program, – i.e. does it follow the syntax rules? Generate object code
26
BNF (Backus-Naur form) (also called Backus Normal Form) a language used to define the syntax rules of a programming language consists of – productions – rules for forming some construct of the language – meta-symbols – symbols of BNF that are NOT part of the language being compiled – terminals – appear as shown – non-terminals – syntax defined by another production
27
BNF Syntax Rules for a simplified boolean expression – bexpr -> bterm || bexpr | bterm – bterm -> bfactor && bterm | bfactor – bfactor -> !bfactor | (bexpr) | true | false | ident – ident -> alpha { alpha | digit|_} – alpha -> a.. z | A.. Z – digit -> 0.. 9 meta-symbols are in red terminals are in blue non-terminals are in black special rules needed for "|" as part of a language
28
bexpr -> bterm || bterm | bterm What sequence of tokens is a valid bexpr? if (there is a valid bterm) if (nextToken is ||) if (there is a valid bterm) return true else return false else return true else return false Note: tokenizer must watch for the "||" without stopping at the first "|"
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.