You are on page 1of 2

Stacks Stacks: Push and Pop An Example Stack Operations

• A Stack is a sequential organization of items in • The operation push(x) places the item x onto the Assume we have a stack of size 3 which holds integers
which the last element inserted is the first element top of the stack. between -100 and 100. Here is a series of operations,
removed. They are often referred to as LIFO, and the results.
which stands for “last in first out.” • The operation pop() removes the top item from
the stack, and returns that item.
• Examples: letter basket, stack of trays, stack of Operation Stack Contents Return
plates. • We need some way of detecting an empty stack
(This is an underfull stack). create ()
• The only element of a stack that may be accessed – In some cases, we can have pop() return some push(55) (55) 1
is the one that was most recently inserted. value that couldn’t possibly be on the stack. push(-7) (-7,55) 1
• There are only two basic operations on stacks, the – Example: If the items on the stack are push(16) (16,-7,55) 1
push (insert), and the pop (read and delete). positive integers, we can return “-1” in case of pop (-7,55) 16
underflow.
push(-8) (-8,-7,55) 1
push pop
– In other cases, we may be better off simply
push(23) (-8,-7,55) 0
keeping track of the size of the stack.
pop (-7,55) -8
• In some cases, we will also have to worry about
pop (55) -7
filling the stack (called overflow). One way to do
this is to have push(x) return “1” if it is pop () 55
Stack
successful, and “0” if it fails. pop () 101

Example Application of Stacks


Example of Array Implementation of
Stack • Stacks can be used to check a program for
balanced symbols (such as {},(),[ ]).
• We use an array E[0..4] to store the elements and
a variable p to keep track of the top. The last • Example: {()} is legal, as is {()({})}, whereas
column, labeled “R” is the result of the function {((} and {(}) are not (so simply counting symbols
Implementing Stacks: Array does not work).
call.
• Stacks can be implemented with an array and an • If the symbols are balanced correctly, then when a
integer p that stores the array index of the top of Operation p E0 E1 E2 E3 E4 R closing symbol is seen, it should match the “most
create -1 ? ? ? ? ?
the stack. recently seen” unclosed opening symbol.
push(55) 0 55 ? ? ? ? 1
• Empty stack has p = -1, and a full stack has p push(-7) 1 55 -7 ? ? ? 1 Therefore, a stack will be appropriate.
push(16) 2 55 -7 16 ? ? 1
= n-1, where n is the size of the array. pop 1 55 -7 16 ? ? 16
The following algorithm will do the trick:
• To push, increment the p counter, and write in the push(-8) 2 55 -7 -8 ? ? 1
• While there is still input:
pop 1 55 -7 -8 ? ? -8
array position. pop 0 55 -7 -8 ? ? -7 s = next symbol
• To pop, decrement the p counter. if (s is an opening symbol) push(s)
• Notice that some values are still in the array, but else //s is a closing symbol
are no longer considered to be in the stack. In if (Stack.Empty) report an error
general, elements E[i] are “garbage” if i > p. else r = pop()
Why don’t we erase the element (i.e. set it to if(! Match(s,r)) report an error
some default value.)?
• If (! Stack.Empty) report an error
Operator Precedence Parsing
Stack: C++ Array Implementation
• We can use the stack class we just defined to parse
• The following is a C++ stack that holds items of and evaluate mathematical expressions like:
Examples type ItemType
5 ∗ (((9 + 8) ∗ (4 ∗ 6)) + 7)
class Stack
1. Input: { ( ) }
{ • First, we transform it to postfix notation:
• Read {, so push { private:
ItemType *stack; 598+46∗∗7+∗
• Read (, so push (. Stack has { ( int p; • Then, the following C++ routine uses a stack to
public:
• Read ), so pop. popped item is ( which matches ). perform this evaluation:
Stack(int max=100)
Stack has now {. char c; Stack acc(50); int x;
{stack = new ItemType[max];
• Read }, so pop; popped item is { which matches }. p = -1; } while (cin.get(c))
˜Stack() {
• End of file; stack is empty, so the string is valid. {delete [] stack; } x = 0;
void push(ItemType v) while (c == ’ ’ ) cin.get(c);
2. Input: { ( ) ( { ) } } (This will fail.)
{ stack[++p] = v; } if (c == ’+’) x = acc.pop() + acc.pop();
2. Input: { ( { } ){ } ( ) } (This will succeed.) ItemType pop() if (c == ’*’) x = acc.pop() * acc.pop();
3. Input: { ( ) } ) (This will fail.) {return stack[p--]; } while (c>=’0’ && c<=’9’)
bool empty() {x = 10*x + (c-’0’); cin.get(c); }
{return (p==-1); } acc.push(x);
}; }
cout << acc.pop() << ’\n’;

Stack Implementation: Stack Implementation:


C++ Linked Lists
Array or Linked List?
• We can use linked lists to implement stacks.
Linked Lists
• The head of the list represents the top of the stack.
• Use 1 pointer extra memory per item. If an item is
Stack Applications
• Example After push(D), push(C), push(B),
an integer, that means twice as much space is • Recursion removal can be done with stacks.
push(A), we have:
used. If an item is a structure/class consisting of
Head
many objects, it is only a small price to pay. • Reversing things is easily done with stacks.
A B C D
• Are unlimited in size. • Procedure call and procedure return is similar to
• ItemType pop () { matching symbols:
Arrays
ItemType x = head->key; – When a procedure returns, it returns to the
head=head->next; • Allocate a constant amount of space, some of most recently active procedure.
return x; } which may never be used. The amount of wasted – When a procedure call is made, save current
memory is the number of unused elements times state on the stack. On return, restore the state
• void push(ItemType x) { the size of the item, which could be large in some
node *x; by popping the stack.
cases.
x=new node;
x->key = X; • The maximum size is determined when the stack
insert(x); } is created.

• Note: Slight error in pop. What is it? Which is better? Why?

You might also like