p o P nd

advertisement
Stack
pop
• To pop, decrement the p counter.
• To push, increment the p counter, and write in the
array position.
• Empty stack has p = -1, and a full stack has p
= n-1, where n is the size of the array.
• Stacks can be implemented with an array and an
integer p that stores the array index of the top of
the stack.
Implementing Stacks: Array
push
• There are only two basic operations on stacks, the
push (insert), and the pop (read and delete).
• The only element of a stack that may be accessed
is the one that was most recently inserted.
• Examples: letter basket, stack of trays, stack of
plates.
• The operation push(x) places the item x onto the
top of the stack.
• A Stack is a sequential organization of items in
which the last element inserted is the first element
removed. They are often referred to as LIFO,
which stands for “last in first out.”
p
-1
0
1
2
1
2
1
0
E0
?
55
55
55
55
55
55
55
E1
?
?
-7
-7
-7
-7
-7
-7
E2
?
?
?
16
16
-8
-8
-8
E3
?
?
?
?
?
?
?
?
E4
?
?
?
?
?
?
?
?
1
1
1
16
1
-8
-7
R
• Notice that some values are still in the array, but
are no longer considered to be in the stack. In
general, elements E[i] are “garbage” if i > p.
Why don’t we erase the element (i.e. set it to
some default value.)?
Operation
create
push(55)
push(-7)
push(16)
pop
push(-8)
pop
pop
• We use an array E[0..4] to store the elements and
a variable p to keep track of the top. The last
column, labeled “R” is the result of the function
call.
Example of Array Implementation of
Stack
• In some cases, we will also have to worry about
filling the stack (called overflow). One way to do
this is to have push(x) return “1” if it is
successful, and “0” if it fails.
• We need some way of detecting an empty stack
(This is an underfull stack).
– In some cases, we can have pop() return some
value that couldn’t possibly be on the stack.
– Example: If the items on the stack are
positive integers, we can return “-1” in case of
underflow.
– In other cases, we may be better off simply
keeping track of the size of the stack.
• The operation pop() removes the top item from
the stack, and returns that item.
Stacks: Push and Pop
Stacks
()
(55)
(-7,55)
(16,-7,55)
(-7,55)
(-8,-7,55)
(-8,-7,55)
(-7,55)
(55)
()
()
create
push(55)
push(-7)
push(16)
pop
push(-8)
push(23)
pop
pop
pop
pop
1
1
1
16
1
0
-8
-7
55
101
Return
• If (! Stack.Empty) report an error
• While there is still input:
s = next symbol
if (s is an opening symbol) push(s)
else
//s is a closing symbol
if (Stack.Empty) report an error
else r = pop()
if(! Match(s,r)) report an error
The following algorithm will do the trick:
• If the symbols are balanced correctly, then when a
closing symbol is seen, it should match the “most
recently seen” unclosed opening symbol.
Therefore, a stack will be appropriate.
• Example: {()} is legal, as is {()({})}, whereas
{((} and {(}) are not (so simply counting symbols
does not work).
• Stacks can be used to check a program for
balanced symbols (such as {},(),[ ]).
Example Application of Stacks
Stack Contents
Operation
Assume we have a stack of size 3 which holds integers
between -100 and 100. Here is a series of operations,
and the results.
An Example Stack Operations
(This will fail.)
(This will fail.)
(This will succeed.)
A
B
C
• Note: Slight error in pop. What is it?
• void push(ItemType x) {
node *x;
x=new node;
x->key = X;
insert(x); }
• ItemType pop () {
ItemType x = head->key;
head=head->next;
return x; }
Head
D
• Example After push(D), push(C), push(B),
push(A), we have:
• The head of the list represents the top of the stack.
• We can use linked lists to implement stacks.
Stack Implementation:
C++ Linked Lists
3. Input: { ( ) } )
2. Input: { ( { } ){ } ( ) }
2. Input: { ( ) ( { ) } }
• End of file; stack is empty, so the string is valid.
• Read }, so pop; popped item is { which matches }.
• Read ), so pop. popped item is ( which matches ).
Stack has now {.
• Read (, so push (. Stack has { (
• Read {, so push {
1. Input: { ( ) }
Examples
Which is better? Why?
• The maximum size is determined when the stack
is created.
• Allocate a constant amount of space, some of
which may never be used. The amount of wasted
memory is the number of unused elements times
the size of the item, which could be large in some
cases.
Arrays
• Are unlimited in size.
• Use 1 pointer extra memory per item. If an item is
an integer, that means twice as much space is
used. If an item is a structure/class consisting of
many objects, it is only a small price to pay.
Linked Lists
Stack Implementation:
Array or Linked List?
class Stack
{
private:
ItemType *stack;
int p;
public:
Stack(int max=100)
{stack = new ItemType[max];
p = -1; }
˜Stack()
{delete [] stack; }
void push(ItemType v)
{ stack[++p] = v; }
ItemType pop()
{return stack[p--]; }
bool empty()
{return (p==-1); }
};
• The following is a C++ stack that holds items of
type ItemType
Stack: C++ Array Implementation
• Procedure call and procedure return is similar to
matching symbols:
– When a procedure returns, it returns to the
most recently active procedure.
– When a procedure call is made, save current
state on the stack. On return, restore the state
by popping the stack.
• Reversing things is easily done with stacks.
• Recursion removal can be done with stacks.
Stack Applications
char c; Stack acc(50); int x;
while (cin.get(c))
{
x = 0;
while (c == ’ ’ ) cin.get(c);
if (c == ’+’) x = acc.pop() + acc.pop();
if (c == ’*’) x = acc.pop() * acc.pop();
while (c>=’0’ && c<=’9’)
{x = 10*x + (c-’0’); cin.get(c); }
acc.push(x);
}
cout << acc.pop() << ’\n’;
• Then, the following C++ routine uses a stack to
perform this evaluation:
598+46∗∗7+∗
• First, we transform it to postfix notation:
5 ∗ (((9 + 8) ∗ (4 ∗ 6)) + 7)
• We can use the stack class we just defined to parse
and evaluate mathematical expressions like:
Operator Precedence Parsing
Chapter Objectives
•
•
•
•
•
•
•
Chapter 7
Stacks
Data Structures Using C++
1
Stacks
Learn about stacks
Examine various stack operations
Learn how to implement a stack as an array
Learn how to implement a stack as a linked list
Discover stack applications
Learn to use a stack to remove recursion
Become aware of the STL class stack
Data Structures Using C++
2
Various Types of Stacks
• Definition: list of homogeneous elements,
wherein the addition and deletion of
elements occur only at one end, called the
top of the stack
• Last In First Out (LIFO) data structure
• Used to implement function calls
• Used to convert recursive algorithms
(especially not tail recursive) into
nonrecursive algorithms
Data Structures Using C++
3
LIFO
Data Structures Using C++
4
Empty Stack
• Last In First Out (LIFO) data structure
– Top element of stack is last element to be added
to stack
– Elements added and removed from one end
(top)
– Item added last are removed first
Data Structures Using C++
5
Data Structures Using C++
6
1
Stack Operations
Basic Operations on a Stack
• initializeStack: Initializes the stack to an
empty state
• destroyStack: Removes all the elements
from the stack, leaving the stack empty
• isEmptyStack: Checks whether the stack is
empty. If empty, it returns true; otherwise, it
returns false
Data Structures Using C++
7
Basic Operations on a Stack
• top: Returns the top element of the stack.
Prior to this operation, the stack must exist
and must not be empty.
• pop: Removes the top element of the stack.
Prior to this operation, the stack must exist
and must not be empty.
– Add new element to the top of the stack
– The input consists of the stack and the new element.
– Prior to this operation, the stack must exist and must
not be full
9
Example of a Stack
Data Structures Using C++
8
Basic Operations on a Stack
• isFullStack: Checks whether the stack is full. If
full, it returns true; otherwise, it returns false
• push:
Data Structures Using C++
Data Structures Using C++
Data Structures Using C++
10
Empty Stack
11
Data Structures Using C++
12
2
initializeStack and destroyStack
emptyStack and fullStack
template<class Type>
void stackType<Type>::initializeStack()
{
stackTop = 0;
}//end initializeStack
template<class Type>
bool stackType<Type>::isEmptyStack()
{
return(stackTop == 0);
}//end isEmptyStack
template<class Type>
void stackType<Type>::destroyStack()
{
stackTop = 0;
}//end destroyStack
template<class Type>
bool stackType<Type>::isFullStack()
{
return(stackTop == maxStackSize);
}//end isFullStack
Data Structures Using C++
13
Push
Data Structures Using C++
14
Push
template<class Type>
void stackType<Type>::push(const Type& newItem)
{
if(!isFullStack())
{
list[stackTop] = newItem;
//add newItem at the top
//of the stack
stackTop++;
//increment stackTop
}
else
cerr<<"Cannot add to a full stack."<<endl;
}//end push
Data Structures Using C++
15
Return Top Element
template<class Type>
Type stackType<Type>::top()
{
assert(stackTop != 0);
return list[stackTop - 1];
16
Pop
//if the stack is empty,
//terminate the program
//return the element of the
//stack indicated by
//stackTop - 1
}//end top
Data Structures Using C++
Data Structures Using C++
17
template<class Type>
void stackType<Type>::pop()
{
if(!isEmptyStack())
stackTop--;
//decrement stackTop
else
cerr<<"Cannot remove from an empty stack."<<endl;
}//end pop
Data Structures Using C++
18
3
Pop
copyStack
template<class Type>
void stackType<Type>::copyStack(const stackType<Type>& otherStack)
{
delete [] list;
maxStackSize = otherStack.maxStackSize;
stackTop = otherStack.stackTop;
list = new Type[maxStackSize];
assert(list != NULL);
//copy otherStack into this stack
for(int j = 0; j < stackTop; j++)
list[j] = otherStack.list[j];
}//end copyStack
Data Structures Using C++
19
20
Overloading the Assignment
Operator (=)
Copy Constructor
template<class Type>
stackType<Type>::stackType(const stackType<Type>& otherStack)
{
list = NULL;
copyStack(otherStack);
}//end copy constructor
Data Structures Using C++
Data Structures Using C++
template<class Type>
const stackType<Type>& stackType<Type>::operator=
(const stackType<Type>& otherStack)
{
if(this != &otherStack) //avoid self-copy
copyStack(otherStack);
return *this;
}//end operator=
21
Time-Complexity of Operations
of class stackType
Data Structures Using C++
22
Stack Header File
//Header file: myStack.h
#ifndef H_StackType
#define H_StackType
#include <iostream>
#include <cassert>
using namespace std;
//Place the definition of the class template stackType, as given
//previously in this chapter, here.
//Place the definitions of the member functions, as discussed in
//this chapter, here.
#endif
Data Structures Using C++
23
Data Structures Using C++
24
4
Programming Example: Highest
GPA
1.
2.
3.
4.
Declare the variables.
Open the input file.
If the input file does not exist, exit the program.
Set the output of the floating-point numbers to a
fixed decimal format with a decimal point and
trailing zeroes. Also, set the precision to two
decimal places.
5. Read the GPA and student name.
6. highestGPA = GPA;
7. Initialize the stack.
Input The program reads an input file consisting of each
student’s GPA, followed by the student’s name. Sample
data is:
3.8
3.6
3.9
3.7
3.4
3.9
3.4
Lisa
John
Susan
Kathy
Jason
David
Jack
Data Structures Using C++
25
Programming Example: Highest
GPA (Algorithm)
27
Input File (Ch7_HighestGPAData.txt)
Holt
Bolt
Colt
Tom
Ron
Mickey
Pluto
Donald
Cindy
Dome
Andy
Fox
Minnie
Goofy
Doc
Danny
26
9. Output the highest GPA.
10. Output the names of the students having the highest
GPA.
Programming Example: Highest
GPA (Sample Run)
3.4
3.2
2.5
3.4
3.8
3.8
3.6
3.5
3.8
3.7
3.9
3.8
3.9
2.7
3.9
3.4
Data Structures Using C++
Programming Example: Highest
GPA (Algorithm)
8. while (not end of file)
{
8.1 if (GPA > highestGPA)
{
8.1.1 destroyStack(stack);
8.1.2 push(stack, student name);
8.1.3 highestGPA = GPA;
}
8.2 else
if(GPA is equal to highestGPA)
push(stack, student name);
8.3 Read the GPA and student name;
}
Data Structures Using C++
Programming Example: Highest
GPA (Algorithm)
Data Structures Using C++
28
Programming Example: Highest
GPA (Sample Run)
Output
Highest GPA = 3.90
The students holding the highest GPA are:
Doc
Minnie
Andy
Data Structures Using C++
29
Data Structures Using C++
30
5
Empty and Nonempty
Linked Stack
Default Constructor
template<class Type> //default constructor
linkedStackType<Type>::linkedStackType()
{
stackTop = NULL;
}
Empty linked stack
Nonempty linked stack
Data Structures Using C++
31
Destroy Stack
//while there are elements
//in the stack
{
temp = stackTop;
//set temp to point to
//the current node
stackTop = stackTop->link; //advance stackTop
//to the next node
delete temp;
//deallocate the memory
//occupied by temp
}
}//end destroyStack
Data Structures Using C++
33
template<class Type>
void linkedStackType<Type>:: initializeStack()
{
destroyStack();
}
template<class Type>
bool linkedStackType<Type>::isEmptyStack()
{
return(stackTop == NULL);
}
template<class Type>
bool linkedStackType<Type>::isFullStack()
{
return false;
Data Structures Using C++
Push
Stack before the push
operation
32
initializeStack and isStackEmpty
template<class Type>
void linkedStackType<Type>::destroyStack()
{
nodeType<Type> *temp;
//pointer to delete the node
while(stackTop != NULL)
Data Structures Using C++
34
Push
Stack and newNode
Stack after the statement
newNode->link = stackTop;
executes
Data Structures Using C++
35
Stack after the statement
stackTop = newNode;
executes
Data Structures Using C++
36
6
Pop
Return Top Element
template<class Type>
Type linkedStackType<Type>::top()
{
assert(stackTop != NULL);
return stackTop->info;
}//end top
//if the stack is empty,
//terminate the program
//return the top element
Stack before the pop operation
Data Structures Using C++
37
Pop
Stack after the statements temp = stackTop;
and stackTop = stackTop->link; execute
Stack after the statement delete temp;
executes
39
Application of Stacks:
Postfix Expression Calculator
Stack after pushing 3
38
Application of Stacks:
Postfix Expression Calculator
Data Structures Using C++
Stack after pushing 6
Data Structures Using C++
40
Application of Stacks:
Postfix Expression Calculator
Stack after retrieving the top two elements
and popping twice
Stack after pushing the result of op1 +
op2, which is 9
Data Structures Using C++
Data Structures Using C++
41
Stack after pushing the result of op1 *
op2, which is 18
Stack after pushing 2
Stack after retrieving the top two elements
and popping twice
Stack after popping the element
Data Structures Using C++
42
7
Postfix Expression Calculator (Main Algorithm)
Nonrecursive Algorithm to
reverse linked list
current = first;
while(current != NULL)
{
stack.push(current);
current = current->link;
}
llistType, *newfirst = stack.pop();
current = newfirst;
while (!stack.empty())
current->link = stack.pop();
current->link = NULL;
Data Structures Using C++
43
List After Execution of Statement
current = first;
Data Structures Using C++
45
STL class stack
(Stack Container Adapter)
Data Structures Using C++
44
Repeated Execution of:
stack.push(current);
current = current->link;
Data Structures Using C++
46
Operations on a stack Object
• Standard Template Library (STL) provides
a class to implement a stack in a program
• Name of the class defining a stack is
“stack”
• Name of the header file containing the
definition of the class stack is “stack”
Data Structures Using C++
47
Data Structures Using C++
48
8
Download