push pop LIFO list only top element is visible t op Defining the ADT Stack Data a linear collection of data items in which all operations occur at one end called the top Basic Operations ID: 760800
Download Presentation The PPT/PDF document "Stacks & Recursion Stack" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Stacks & Recursion
Slide2Stack
push
pop
LIFO list - only top element is visible
t
op
Slide3Defining 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
Slide4Some 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
Slide5Implementation example
-1
myTop
myArray
7
6
5
4
3
2
1
0
typedef
Complx StackElement;const int CAPACITY = 8;int myTop;StackElement myStack[CAPACITY];Complx X;push(&myStack,X);
initially
empty
(
myTop
is negative)
Slide6Nyhoff, 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 arrayLet position 0 be top of stackProblem … consider pushing and poppingRequires much shifting
Slide7Nyhoff, 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 stackThus our design will includeAn array to hold the stack elementsAn integer to indicate the top of the stack
Slide8Addressing 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
Slide9The "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
]
;
Slide10Recursion
An alternative to loops
Slide11What is recursion?
a function calls itselfdirect recursiona function calls its callerindirect recursion
f
f1
f2
Slide12Recursion-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
Slide13Head 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
Slide14Head vs. Tail recursionNote: 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);
);
}
Slide15Caveats
S
tatic data is NOT on the "stack"
never gets re-allocated
same values for EVERY call
Must have an "exit"
prevent an infinite loop
Slide16Outline of a Recursive Function
if (answer is known) provide the answer & exitelse call same function with a smaller version of the same problem
base
case
recursive
case
Slide17Factorial (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
Slide18Factorial (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
}
Slide19Factorial "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));
Slide20Keeping track
compiler builds code to:
create a new stack pointer and stack space
put local variables & parameters
o
n 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"
Slide21Recursive 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
Slide22Fibonacci 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>2for n=4: fib(2)+fib(3) 1 + 2 3
Slide23Tracing fib(6)
2
1
3
2
4
3
2
1
5
6
4
2
1
3
2
1
1
1
+
Slide24Ackermann'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
))
Slide25What 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
Slide26BNF (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
Slide27BNF 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
Slide28bexpr -> 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 "|"