You are on page 1of 37

More on Stacks and Queues

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

As we mentioned before, two common introductory Abstract Data Type (ADT) that worth studying are Stack and Queue Many problems (or parts of problems) can be thought of as stack problems, queue problems, or other problems that can be solved with the help of another (perhaps user-defined) ADT

You need to decide what ADTs you need, build them, test them, then tackle your larger problem

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

Stack ADT
A stack is an ADT with specific properties and operations Stack properties are: Only one item can be accessed at a time Always the last item inserted is the first to come out (LIFO)

New items must be inserted at the top


The size of the stack is dynamic

The stack must be able to grow and shrink


Normally, items stored on the stack are homogeneous (i. e. they are all integers or all are string, etc
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 3

Stack Operations
Stack operations are: Push: Puts a new item on the top of the stack. Cant push into a full stack Pop: Removes the top item from stack. Cant pop an empty stack Top: Examine top item without modifying stack. Cant top an empty stack Init: Set existing stack to empty Full: Returns true if the stack is full Empty: Returns true if the stack is empty
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 4

Problem Solving Using Stack: Bracket Checking


Many problems can be solved using stacks Given a mathematical expression with 3 types of brackets ( ) [ ] { }, we want to determine if the brackets are properly matched For example, bracketing in the following expression is CORRECT { 5 * (8-2) } / { [4 * (3+2)] + [5 * 6] } However, the bracketing in the following two expressions are INCORRECT { (A+C) * D [A + {B+C} )
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 5

This problem is easily solved with a stack


Algorithm: Scan expression from left to right Each time a left bracket is encountered, push it onto the stack When a right bracket is encountered, compare it to the top item on the stack If its a match, pop the stack If not, report illegal bracketing If the stack is prematurely empty, report illegal bracketing If there are items left on the stack after the expression has been scanned, report illegal bracketing
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 6

This program assumes bool BracketMaching (string expression) that we have the { following routines char curr, temp; available Stack bracket_stack; for (int i=0; i< stg.size(); i++) bool empty (); { push (item); curr = stg[i]; char top (); if (curr == ( || curr == [ || curr == {) bracket_stack.push (curr); else if (curr == ) || curr == ] || curr == }) if (bracket_stack.empty() ) then return false; else if (bracket_stack.pop() does not match with curr) return false; end if end if } // for loop

return true; }
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 7

Problem Solving Using Stack: Evaluation of An Expression


Consider the problem of evaluating an arithmetic expression using a stack Traditionally, when we write an arithmetic expression as follows: 2 + 3 * (6 - 5) This is known as infix notation Operators are in-between the operands When computing arithmetic expressions, its sometimes useful to represent them using postfix (operator after) or prefix (operator before) notation
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 8

Prefix -61 *+432 /+23-94

Infix 6-1 (4 + 3) * 2 (2 + 3) / (9 - 4)

Postfix 6143+2* 23+94-/

Its easy to evaluate postfix and prefix expressions using a stack in part because no brackets are necessary

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

prefix *+432 evaluate 4 7 + 3 2 * 14 2 Push 2 Push 3 Push 4 Pop 4 Pop 3 Apply + and get 7 Push 7 Pop 7 Pop 2 Apply * and get 14 Push 14
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University

postfix
43+2*

3 2 * 14 4 + 7 push 4 push 3 Pop 3 Pop 4 Apply addition and get 7 Push 7 Push 2 Pop 2 Pop 7 Apply * and get 14 Push 14
Page 10

Algorithm for evaluating postfix: Parse expression from left to right When an operand is encountered, push it onto the stack

When an operator is encountered, pop the top two operands, apply the operator, and push the result onto the stack
When the expression is completely scanned, the final result will be on the stack What if we want to convert an expression from infix to postfix? For example: 2 + 3 * [(5 - 6) / 2] becomes 2356-2/*+
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 11

Use the following algorithm to change infix to postfix:

Scan infix string from left to right


Each time an operand is encountered, copy it to the output When a bracket is encountered, check its orientation. Push left brackets onto the stack If its a right bracket, pop all operators out of the stack and copy them to output until a matching left bracket is encountered. Discard the left bracket. When an operator is encountered, check the top item of the stack. If the priority is >= the current operator, pop the top operator and copy it to output Continue until an operator of lesser priority is encountered or until stack is empty Assume left brackets have lowest priority Finally, push current operator onto the stack When the end of the expression is reached, copy the remaining stack contents to output in the order popped
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 12

Consider the following example that is scanned from left to right Expression: 2+3*[(56)/2]

Stack

Output:

2 is placed on the output line because it is an operand Expression: 2+3*[(56)/2] Stack

Output:

+ is an operator and it is placed in the stack. Note there is no operator on the top of the stack with priority >= the + operator
Page 13

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Expression: 2+3*[(56)/2]

Stack

Output:

23

3 is placed on the output line because it is an operand

Expression: 2+3*[(56)/2]

Stack

Output:

23

* +
A.R. Hadaegh Dr. Ahmad R. Hadaegh

* is an operator and it is placed in the stack without taking anything out of the stack. Note that * has higher priority than +
Page 14

National University

Expression: 2+3*[(56)/2]

Stack

Output:

23

[ * +

Left brackets, no matter what type of bracket it is, it is placed in the stack

Expression: 2+3*[(56)/2]

Stack ( [ * +

Output:

23

Again another left encountered and it is placed in the stack

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

15

Expression: 2+3*[(56)/2]

Stack

Output:

235

( [ * +

5 is placed on the output line because it is an operand

Expression: 2+3*[(56)/2]

Stack Output: 235 ( Minus sign (-) is placed in the [ stack. Note that the top of the * stack is not an operator to + compare minus sign with it
National University Page 16

A.R. Hadaegh Dr. Ahmad R. Hadaegh

Expression: 2+3*[(56)/2]

Stack Output: 2356 ( [ 6 is placed on the output line * because it is an operand +

Expression: 2+3*[(56)/2]

Stack

Output:

2356-

[ * +
A.R. Hadaegh Dr. Ahmad R. Hadaegh

( is a closing round bracket. Keep on popping from the stack till we you find the matching opening round bracket. DO NOT COPY THE OPEN ROUND BRACKET TO THE OUTPUT
Page 17

National University

Expression: 2+3*[(56)/2]

Stack / [ * +

Output:

2356-

Division (/) is placed in the stack. Note that the top of the stack is not an operator to compare division sign with it

Expression: 2+3*[(56)/2]

Stack / [ * +

Output:

2356-2

2 is placed on the output line because it is an operand

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

18

Expression: 2+3*[(56)/2]

Stack

Output:

2356-2/

* + Stack

] is a closing square bracket. Keep on popping from the stack till we you find the matching opening square bracket. DO NOT COPY THE OPEN SQUARE BRACKET TO THE OUTPUT

Expression: 2+3*[(56)/2]

Output:

23562/*+

We are done. So keep popping from the stack and place the characters to the output line

What we have on the output line is the corresponding postfix expression


A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 19

Problem Solving Using Stack: Adding large numbers using stack


Another example of stack application is adding two large numbers together. Note that the largest magnitude of integers are limited so we are not able to normally add numbers like: 243678489505654679857465758598595950949463535 + 462668435748955758056548577946 Since the integer variables cannot hold such a big numbers we can use other tools to add these numbers together The next slide shows the algorithm of adding two numbers together using stack
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 20

Algorithm for adding two numbers


Read the numerals of the first number and store the numbers corresponding to them on the stack; Read the numerals of the second number and store them in another stack; Let R = 0; While at least one stack is not empty Pop a number from each stack and add them to R; Push the unit part of R on the result stack; Store carry part of R in R overwriting the old value; Push R on the result stack if it is not zero Pop numbers from the result stack and display them
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 21

592 + 3784 4376

2 +4 6

9 +8 17

1 5 +7 13

1 +3 4

2 Stack 1 9 5

9 5

+ =6
4 Stack 2 8 7 3 8 7 3

+ =17
7 3

+ =13

+ =4

Result Stack
A.R. Hadaegh Dr. Ahmad R. Hadaegh

7 6
National University

3 7 6

4 3 7 6
Page 22

Problem Solving Using Stack: Exiting A Maze


Consider the problem of a trapped mouse that tries to find its way to an exit in a maze The mouse systematically moves and if it hits a wall, it backtracks and tries another path. The maze is implemented as a two dimensional character array in which passages are marked with o and walls are marked with 1.

When a cell is visited, it is marked with . so that the mouse does not try that again.
In general, the mouse always takes right cell first, if it cannot succeed, it takes left and if it still fails, it takes down and finally it tries the upper cell to reach its destination. As long as it finds a space it moves in that path and tries its best to find the exit door. We represent the mouse with M and exit door with E
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 23

In order to ensure that the mouse does not fall off the maze, we create a wall around the maze.
Thus the mouse will be trapped in the maze until it finds the door.

If the mouse tries all the possible solutions and still cannot find the exit door, we report a failure; otherwise, we report a success.
The algorithm is:
Initialize stack, exitCell, entryCell, currentCell = entryCell; Create a wall of 1s around the maze While currentCell is not exitCell Mark currentCell as visited; Push onto the stack the unvisited neighbors of current Cell in the order of up, down left and right If stack is empty Report failure Else Pop off a cell from the stack and make it currentCell success
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 24

0 1 2 3 4 5

Start with the following maze where the mouse is at position (3, 3) and the exit door is at (2, 4)

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1 1 o o o E 1 1 o o M 1 1 1 1 1 1 1 1

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1 1 o o o E 1 1 o o M 1 1 1 1 1 1 1 1

Push the Up and Left cell into stack

Make the current position visited (.) Pop the first element of the stack Move the mouse to that position

(3, 2) (2, 3)

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

25

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1

Push the Up and Left cells into stack

Make the current position visited (.) Pop the first element of the stack Move the mouse to that position

1 o o o E 1
1 o M . 1 1 1 1 1 1 1 1

(3, 1) (2, 2) (2, 3)

0 1 2 3 4 5

Push the Up cell into stack

Make the current position visited (.)


Pop the first element of the stack Move the mouse to that position

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1 1 o o o E 1 1 M . . 1 1 1 1 1 1 1 1
National University

(2, 1) (2, 2) (2, 3)

A.R. Hadaegh Dr. Ahmad R. Hadaegh

Page

26

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1

Push the Right cell into stack

Make the current position visited (.) Pop the first element of the stack Move the mouse to that position

1 M o o E 1
1 . . . 1 1 1 1 1 1 1 1

(2, 2) (2, 2) (2, 3)

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1 1 . 1 . M o E 1 . . 1 1

Push the Right cell into stack

Make the current position visited (.)


Pop the first element of the stack Move the mouse to that position

(2, 3) (2, 2) (2, 3)

1 1 1 1 1 1
National University

A.R. Hadaegh Dr. Ahmad R. Hadaegh

Page

27

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 1 1 o o 1

Push the UP and Right cell into stack

Make the current position visited (.) Pop the first element of the stack Move the mouse to that position

1 .
1 .

.
.

M E 1
. 1 1

1 1 1 1 1 1

(2, 4) (1, 3) (2, 2) (2, 3)

0 1 2 3 4 5

0 1 2 3 4

1 1 1 1 1 1 1 o 1 . 1 . . . . .

1 o 1 1

1 1 1 1

Push the UP cell into stack

E/M 1

1 1 1 1

(1, 3) (2, 2) (2, 3)


National University

The exit door is found

A.R. Hadaegh Dr. Ahmad R. Hadaegh

Page

28

Queue
A queue is an ADT with the following specific properties
A queue contains zero or more, normally homogenous, items Data items are added to the tail (back) of the queue and are removed from the head (front) of the queue

The items in the queue are maintained in FIFO (first-infirst out) order
The first item placed on the queue is always the first one removed
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 29

Possible operations Init: Initializes a queue so as to be empty Insert: Adds a new item to the tail of the queue Remove: Removes the item at the head of the queue

Empty: Tests to see if the queue is empty


Full: Tests to see if the queue is full

Data In

.... Queue tail head


National University

Data Out

A.R. Hadaegh Dr. Ahmad R. Hadaegh

Page

30

Queues are common in computing Scheduling queues Operating systems support multi-tasking by sharing scarce resources such as CPU time Each task that requests CPU resources might be put in a queue Tasks are given cycles of time If task finishes . good -- if not, task goes to the back of queue for additional cycles Lets discuss some implementations of Queue

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

31

Implementing Queue with Array


One possible queue implementation is array Elements are added to the end of he queue , and removed from the beginning of the queue Suppose we insert some element to the bottom of the queue and remove other elements from the head of the queue. Now if we reach to the end of the queue, we cannot insert anymore element to the bottom even if we have some elements remove from the head of the queue.

Therefore, to optimize space, we can turn our queue into a circular queue so that when we reach the end of the queue, we can still insert some element if there is empty space in the head
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 32

Thus, the circular queue is full under when one of the following conditions are true: The head is at position 0 and tail is at position n-1 (last position) The head is at position of tail+1 in the queue The first case is shown in the following example. Suppose, the queue has 4 positions and we insert 10, 20, 30, and 40 without removing any element

head
head head tail 10 head tail 10 20 tail 10 20 30

tail

10 20 30 40

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

33

Now suppose after inserting 30 we pop 10 and we insert 40 and 50. Again the queue is full and head is tail+1 enqueue 10 enqueue 20

enqueue 30 head
10 20 30

dequeue 10 10 20 30

head tail

10

head tail

10 20

tail

head tail

enqueue 40
tail head
A.R. Hadaegh Dr. Ahmad R. Hadaegh

enqueue 50 tail head 40 50 20 30


Page 34

40 10 20 30

National University

The queue is initially empty. The initial value of head and tail is -1 and if during the operation we pop one element from the queue and we find out that the head and tail becomes equal
void Queue::enqueue(int e1) { if (! isFull()) { if (last == size -1 || last == -1) { storage[0] = e1; last = 0; if (first == -1) first = 0; } else { last++; storage[last] = e1; } } else cout <<Queue is full" << endl; }

class Queue { public: Queue(){last = first = -1, size =4;} void enqueue(int); int dequeue(); bool isFull() { return ( (first==0 && last == size-1) || (first==last+1) ); } bool isEmpty(){return first==-1;} private: int first, last, size; int storage[4]; }; int Queue::dequeue() { int tmp; if (isEmpty()) { cout << "Queue is empty " << endl; return 0; } tmp = storage[first]; if (first==last) last = first = -1; else if (first==size-1) first = 0; else first++; return tmp; }
Page 35

See: example 1
A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Here is the same example with template


template <class T, int size=100> class Queue { public: Queue(){last = first = -1;} void enqueue(T); T dequeue();

The default size is 100 if the size is not determined

bool isFull() { return ( (first==0 && last == size-1) || (first==last+1) ); } bool isEmpty(){return first==-1;} private: int first, last; T storage[size]; };

A.R. Hadaegh Dr. Ahmad R. Hadaegh

National University

Page

36

Here is the same example with template


template <class T, int size> void Queue<T, size>::enqueue(T e1) { if (! isFull()) { if (last == size -1 || last == -1) { storage[0] = e1; last = 0; if (first == -1) first = 0; } else { last++; storage[last] = e1; } } else cout << "Queue is full" << endl; } template <class T, int size> T Queue<T, size>::dequeue() { T tmp; if (isEmpty()) { cout << "Queue is empty " << endl; return tmp; } tmp = storage[first]; if (first==last) last = first = -1; else if (first==size-1) first = 0; else first++; return tmp; }

See: example 2
A.R. Hadaegh Dr. Ahmad R. Hadaegh National University Page 37

You might also like