Vous êtes sur la page 1sur 37

Data Structures

Stacks

1
Solving Maze

2
Objective
Stack Abstract Data Type
Sequential Allocation
Linked Allocation
Applications

3
Stack
 Stack is a list with the restriction that insertions
and deletions (usually all the accesses) can only
be performed at one end of the list
 Also known as: Last-in-first-out (LIFO) list

4
ADT of Stack
Value:
A sequence of items that belong to some data type ITEM_TYPE

Operations for stack s:


1. Boolean IsEmpty()
Postcondition: If the stack is empty, return true, otherwise return false
2. Boolean IsFull()
Postcondition: If the stack is full, return true, otherwise return false
3. ITEM_TYPE Pop() /*take away the top one and return its value*/
Precondition: s is not empty
Postcondition: The top item in s is removed from the sequence and returned
4. ITEM_TYPE top() /*return the top item’s value*/
Precondition: s is not empty
Postcondition: The value of the top item in s is returned
5. Void Push(ITEM_TYPE e) /*add one item on top of the stack*/
Precondition: s is not ______
Postcondition: e is added to the sequence as the top one
5
Array Implementation of Stack
// MyStack.h
#include “stdlib.h” // MyStack.cpp
{
public class MyStack #include “MyStack.h”
{ MyStack::MyStack(int size)
public: {
MyStack( int ); data=new int[size];
bool IsEmpty(); top=-1;
bool IsFull(); MAXSize=size;
void push(int ); }
int pop(); bool MyStack::IsEmpty()
int top(); {
private: return (top==-1);
int* data; }
int top; bool MyStack::IsFull()
int MAXSize; {
}; return (top==MAXSize-1);
} }

6
Array Implementation of Stack
// StackTest.cpp
#include “MyStack.h” Top Item E
int main() Item D
{ Item C
MyStack* TS=new MyStack(100);
}
Item B
Bottom Item A

Bottom of
L0 Slot #0: Item A stack:
In computer memory: Slot #1: Item B
L0+c Always at
Suppose L0+2c Slot #2: Item C first slot
(slot#0)
• Size of each item is c. L0+3c Slot #3: Item D
L0+4c Slot #4: Item E
• Base address is L0. Top of
L0+5c Slot #5: Not yet filled stack
L0+6c Slot #6: Not yet filled (slot#4)
… …
L0+99c Slot #99: Not yet filled
7
Array Implementation of Stack

When the stack is empty, When the stack is FULL,

Top of stack
is Slot #0: filled
undefined Slot #1: filled
Slot #2: filled
Slot #0: Not yet filled
Slot #3: filled
Slot #1: Not yet filled
Slot #4: filled
Slot #2: Not yet filled

Slot #3: Not yet filled
Slot #99: filled
Slot #4: Not yet filled

Slot #99: Not yet filled Top of stack
is at slot #99
ie. Slot #(MAXSTACKSIZE-1)
8
Array Implementation of Stack
To “push” an item onto the stack,

 Check whether not yet full.


private:
int* data;  Increase the top indicator (slot
int top; number) of the stack.
int MAXSize;
 Copy the item to the top position
void MyStack::push(int x) immediately.
{ if (!IsFull() )
{ Slot #0: filled
top=top+1;
Slot #1: filled
data[top] = x;
} Slot #2: filled
else Slot #3: not yetfilled
to be filled
…. Slot #4: not yet filled Top of stack:
slot #2 => 3
} …
Slot #99: not yet filled
9
Array Implementation of Stack
private: To “pop” an item from the stack
int* data; (to take away the top one and
int top; return its value),
int MAXSize;  Check whether it is empty.

 Save the value of item at the top


position (to return it later)
int MyStack::pop( )
 Decrease the top indicator (slot #)
{ int rtn_value;
if (!IsEmpty())  Return the saved value.

{  No need to clear any slot.


rtn_value=data[top];
top=top-1; Slot #0: filled
return rtn_value; Slot #1: filled
} Slot #2: filled
else Slot #3: to be popped
filled Top of stack:
… Slot #4: not yet filled slot #3 => 2
}} …
Slot #99: not yet filled 10
Array Implementation of Stack
To return the value of an item
from the stack (the top item),

private:  Check whether it is empty.


int* data;  Return the value of the item at the
int top; top position.
int MAXSize;

int MyStack::top( ) Slot #0: filled


{ if (!IsEmpty()) Slot #1: filled
{ Slot #2: filled
return (data[top]); Slot #3: to be returned
filled Top of stack:
} Slot #4: not yet filled slot #3
else … (no change)
… Slot #99: not yet filled
}

11
Stacks: Use Dynamic Array
 How to choose the size of array data[]?
 As we insert more and more, eventually the array
will be full
 Solution: Use a dynamic array
 Maintain capacity of data[]
 Double capacity when size=capacity (i.e. full)
 Half capacity when sizecapacity/4
 Question: What if we change capacity/4 to
capacity/2 ?
 E.g., initial cap is 4; I, I, I, I, I (expand; cap=8, size=5), D
(shrink; cap=4, size=4), I (expand; cap=8, size=5), D (shrink;
cap=4, size=4), I (expand), D (shrink), ….
12
Stacks: Another implementation
class Stack
{
public:
Stack(int initCap=100);
Stack(const Stack& rhs);
~Stack();

void push(Item x);


void pop(Item& x);

private:
void realloc(int newCap);
Item* data;
int size;
int cap;
};

13
Stacks: Another implementation
void Stack::push(Item x)
{
if (size==cap) realloc(2*cap);
array[size++]=x;
}

// An internal func. to support resizing of array


void Stack::realloc(int newCap)
{
if (newCap < size) return;
Item *oldarray = data; //oldarray “point to” data
data = new Item[newCap]; //create new space for data
//with a size of newCap
for (int i=0; i<size; i++)
data[i] = oldarray[i];
cap = newCap;
delete [] oldarray;
}
14
Stacks: Another implementation
void Stack::pop(Item& x)
{
if (size==0)
x=EmptyStack;
// assume EmptyStack is a special value
else
{
x=array[--size];
if (size <= cap/4)
realloc(cap/2);
}
}

15
Linked Implementation of Stack
Address T
Top Item E
Top of
Item D e Slot #4: Item E d stack
Item C (slot#4)
Item B
Bottom Item A
d Slot #3: Item D c
• Stack can also be
implemented with linked list. c Slot #2: Item C b
• Typically, a pointer points to
the top of the stack. (T)
b Slot #1: Item B a
• When the stack is empty, this Bottom of
pointer will be NULL. stack:
• Each slot is allocated only a Always
Slot #0: Item A NULL
links to
when it is needed to store an NULL
___
__
item. __
16
Linked Implementation of Stack
// MyStack.h // ListNode.h

#include “stdlib.h” #include “stdlib.h”


{
#include “ListNode.h”
public class ListNode
{ {
public class MyStack public:
{ ListNode( int );
public: ListNode( int, ListNode *);
MyStack( ); ListNode *get_Next()
Pop(); {
IsEmpty(); return next;
Push(int ); }
… …
private: private:
int data;
ListNode *Top;
ListNode *next;
}; };
} }

17
Linked Implementation of Stack
Push: To insert new information Address
onto the top of the stack: p Slot #5: new item e
 Allocate memory for an auxiliary Top
pointer p e Slot #4: Item E d
 Put new item into p->data
 p->next = T
d Slot #3: Item D c
 T=p

void MyStack::Push (int new_item) c Slot #2: Item C b


{ ListNode* p;
p=new ListNode(new_item, Top);
b Slot #1: Item B a
// p->data = new_item;
// p->next = Top;
Top = p; a Slot #0: Item A NULL
} ___
__
__ 18
Linked Implementation of Stack
Pop: To take away (and delete) the Top Item
top item and return its value. (value to be returned)
 Check whether the stack is empty. p
Address
 Store the value of the item so that we can f Slot #5: Top Item e
return it later.
Top
 Update the T pointer to point to the next item.
e Slot #4: Item E d
 Return the value of the top item.

int MyStack::Pop () c
d Slot #3: Item D
{ ListNode* p; //a pointer to point to original top node
int rtn_value; //the value of the item to be returned
c Slot #2: Item C b
if (IsEmpty()) //check whether the stack is empty
{ //Exception handling }
rtn_value=Top->data; //save the value to be returned b Slot #1: Item B a
Top= Top->next; //update the T pointer
a Slot #0: Item A NULL
return (rtn_value); //return the original top node value
} ___
__
__ 19
Application1: Backtracking
Generating a maze Using stacks (simplest way)
1. Start from the entrance cell
2. Randomly select an
unvisited neighbor cell of
the stack top and break
the wall, then push the
new cell onto the stack
3. If all the neighbors are
already visited, then go
back by popping cells from
the stack
4. Until the exit is reached
Try by yourself on a 4*4 maze!

20
Constructing a 4*4 maze

Variables needed
An array memorizing whether a room is visited or not
A stack
An array memorizing whether a wall is broken or not

How to solve a maze?


21
Application 2: Balancing Symbols
 When writing programs, we use () parentheses [] brackets {} braces
 A lack of one symbol may cause the compiler to emit a hundred lines
without identifying the real error
 Using stack to check the balance of symbols
 [ ( ) ] is correct while [ ( ] ) is incorrect
 Read the code until end of file
 If the character is an opening symbol: ( [ {, push it onto the stack
 If the character is a closing symbol: ) ] }, pop one (if the stack is not empty)
from the stack to see whether it is the correct correspondence
 Output error in other cases

22
Application 3
Evaluation of Postfix Expression
Infix Expression Example: (A+B)*((C-D)*E+F)
We need to add “(“ and “)” in many cases.

Postfix Expression Example: AB+CD-E*F+*


Each operator follows the two operands.
The order of the operators (left to right) determines the
actual order of operations in evaluating the expression.
Example 6 2 + 3 1 - 4 * 7 + *
=8 3 1 - 4 * 7 + *
=8 2 4 * 7 + *
=8 8 7 + *
=8 15 *
=120
Prefix expression Example : *+AB+*-CDEF
23
Each operator precedes the two operands.
Application 3
Evaluation of Postfix Expression
6 2 + 3 1 - 4 * 7 + *
=8 3 1 - 4 * 7 + *
=8 2 4 * 7 + *
=8 8 7 + * - * +
=8 15 * + *
1 4 7
=120 2 3 2 2 8 8 15 15
6 8 8 8 8 8 8 8 8 120

The method:
 Scan the expression from left to right.
 For each symbol, if it is an operand, we store them for later operation (LIFO) push
 If the symbol is an operator, take out the latest 2 operands stored and compute
with the operator. pop pop
Treat the operation result as a new operand and store it. push
 Finally, we can obtain the result as the only one operand stored. pop

24
Application 3
Evaluation of Postfix Expression
//check whether the parameter symbol is a digit
bool IsDigit(char symbol)
{ if (symbol >= '0' && symbol <= '9')
return true;
return false;
}
int Compute(char operator, int operand1, int operand2)
{ switch (operator)
{ case '+' : return (operand1 + operand2);
case '-' : return (operand1 - operand2);
case '*' : return (operand1 * operand2);
case '/' : return (operand1 / operand2);
}
}

25
Application 3
Evaluation of Postfix Expression
 …
 using namespace MyStack
 BOOL IsDigit(char symbol) { .. }
 int Compute(char operator, int operand1, int operand2) { .. }
 void main()
 { int i, operand1, operand2, computed_value
 String * exp;
wchar_t c;
 //Input of expression: exp
 Console::Write(S"Enter the expression (no space in-between): ");
 exp=Console::ReadLine();
 //Compute the expression
 Stack *S=new Stack();
 for (i=0; i<exp->GetLength(); i++)
 {
 c=exp->get_Chars(i);
 if (IsDigit(c))
 S.push( (c-'0'));
 else
 { operand2=S.pop();
 operand1=S.pop();
 computed_value=Compute(c,operand1,operand2);
 S.push(computed_value);
 }
 }
 //Output the answer
 Console::Write(S”Answer: {0}”, S.pop());
 }
26
Application 4
Infix expression  postfix expression
Define the precedence relation Operators priority no.
of some of the operators:
# 0
# is the special symbol to denote the ( 1
bottom of stack. + or - 2
* or / 3

Example:(1+3)*((2-4)+5*7) => 1 3 + 2 4 - 5 7 * + *
1 3 + 2 4 - 5 7 * + *

4 ) 7 )
2 - -  5 * * * 
3 ) ( ( ( x + + + + 
1 + +  ( ( ( ( ( ( ( x
( ( ( x * * * * * * * * 
# # # # # # # # # # #27
Application 5: Identify the boundary of lines

 Given several lines, identify which parts of the lines can


been seen if you look from the above

28
Application 5: Identify the boundary of lines

 Algorithm:
Sort the lines according to their slopes l1,l2,…ln
Construct a stack and push the first two lines l1,l2 into it
For k=3 to n
{
Pop two lines from the stack and store them in A and B (A stores the first
popped line)
While the intersection point of A and B is below lk
{
A=B
Pop a line from the stack and store it in B }
Push B, A, lk into the stack in this order 29

}
Identify the boundary of lines
l1

A
B
 Example:

l1
#
30
Identify the boundary of lines
l1

l2

A
B
 Example:

l2
l1
#
31
Identify the boundary of lines
l1

l2

l3

A l2
B l1
 Example:
Processing l3
Intersection point of A and B is above l3
Pop two lines Therefore, l3 together with the value of A
from the stack and B is put on the stack
and store
l2 l3
them in A, B
l1 l2
# # l1
# 32
Identify the boundary of lines
l1

l2

l3

A l32
l4 B l21
 Example: Processing l4 Intersection point of A and B is below l4
Therefore, l3 is abandoned, one more line
Pop two lines
is popped from the stack.
from the stack
l3 The value of A and B becomes l2 and l1
and store
l2 them in A, B
l1 l1
# # #
33
Identify the boundary of lines
l1

l2

l3

A l2
l4 B l1
 Example: Intersection point of A and B is above l4
Therefore, l4 together with A and B is put
on the stack
l3 l4
l2 l2
l1 l1 l1
# # # #
34
Identify the boundary of lines
l1

l2

l3

A l23
l4 B l12
 Example:

Processing l3 Processing l4
l3 l4
l2 l2 l2
l1 l1 l1 l1
# # # # # #
35
Note:
When we use a stack ADT, we should not do anything specific to the internal
data structure. All accesses to the stacks must be made through stack
member functions.
Only the member functions may access the internal data of stacks directly.
Do not access the internal data of stacks in other parts of the programs.

(This note applies also to queue ADT that will be taught in next topic)

36
Learning Objectives
1. Explain the concepts of Stack
2. Understand the three functions of Stack
3. Able to use the three functions to
generate and solve a maze
4. Fully understand how stack is used in
Application 2

D:1; C:1,2; B:1,2,3; A:1,2,3,4

37

Vous aimerez peut-être aussi