Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

28
Stacks & Recursion

Transcript of Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Page 1: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Stacks & Recursion

Page 2: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Stackpush pop

LIFO list - only top element is visible

top

Page 3: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 4: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 5: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Implementation example

-1

myTop

myArray

76543210

typedef Complx StackElement;const int CAPACITY = 8;

int myTop;StackElement myStack[CAPACITY];

Complx X;push(&myStack,X);

initially empty (myTop is negative)

Page 6: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 7: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

7

Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005

Pearson Education, Inc. All rights reserved. 0-13-140909-3

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

Page 8: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 9: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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];

Page 10: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Recursion

An alternative to loops

Page 11: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

What is recursion?

• a function calls itself– direct recursion

• a function calls its caller– indirect recursion

ff1

f2

Page 12: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 13: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 14: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Head vs. Tail recursionNote: base case is ALWAYS 1st

tail(3) is: 3 2 1void tail(int n) {

if(n == 0) return;

else printf("tail - n=%i\

n",n);tail(n-1); //

}

head(3) is: 2 3void head(int n){

if(n == 1) return;

elsehead(n-1); //

printf("head - n=%i\n",n);); }

Page 15: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 16: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Outline of a Recursive Function

if (answer is known) provide the answer & exitelse call same function with a smaller version of the same problem

basecase

recursivecase

Page 17: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Factorial (n) - looping

fact (int n){if (n<0) exit(1);

answer=1;for (i=1; i<=n; i++) answer=answer*i; // loop n

timesreturn (answer);

}• This is a simple problem

Page 18: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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}

Page 19: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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 2nd parameter

return tail_fact (--n, sofar * n); }

// here's how to run itprintf ("5!=%i",tail_fact(5,5));

Page 20: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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"

Page 21: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

24

6

2

Page 22: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Fibonacci Series

Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, ….n= 1 2 3 4

1 for n <= 2fib(n) =

fib(n-2) + fib(n-1) for n>2

for n=4: fib(2)+fib(3)1 + 2 3

Page 23: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

Tracing fib(6)

2 1

3 2

4 3

2 1

5

6

4

2 1

3 2

1 1

1

+

Page 24: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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))

Page 25: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 26: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 27: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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

Page 28: Stacks & Recursion. Stack pushpop LIFO list - only top element is visible top.

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 trueelse return false

• Note: tokenizer must watch for the "||" without stopping at the first "|"