You are on page 1of 106

STACKS AND QUEUES

• Linear Data Structures with restricted insert and


remove disciplines

1
STACKS AND QUEUES

• Linear Data Structures with restricted insert and


remove disciplines
– Last In First Out (LIFO)  Stacks

– First In First Out (FIFO)  Queues

2
STACKS

PUSH D0
PUSH D1
PUSH D2

PUSH D3

D3
D2
D1
D0

3
STACKS

PUSH D0
PUSH D1
PUSH D2

PUSH D3

POP

D2

D1
D0

4
STACKS

PUSH D0
PUSH D1
PUSH D2

PUSH D3

POP
POP

D1
D0

5
STACKS

PUSH D0
PUSH D1
PUSH D2

PUSH D3

POP
POP
PUSH D4
D4

D1
D0

6
STACKS
• You can only insert or
delete at the top of the
stack

D4

D1
D0

7
STACKS
• You can only insert or
delete at the top of the
stack
• Only the data item at top
of the stack is accessible
• Lower items are not
D4
accessible
D1
D0

8
QUEUES

Remove from the front


Insert at the back

9
STACKS AND QUEUES

• If we know the maximum size before hand we


can use an array: this usually possible in many
applications.

10
STACKS AND QUEUES

• If we know the maximum size before hand we


can use an array: this is usually possible in
many applications.

• Otherwise we can use a linked list structure.

11
STACKS

• Maximum stack size not known beforehand.


– Use Linked Lists
• Insert at the front
• Delete at the front

12
STACKS

• Maximum stack size not known beforehand.


– Use Linked Lists
• Insert at the front (push)
• Delete at the front (pop)
• Maximum stack size known beforehand.
– Use vector/one-dimensional array
• Use indexing to implement pop and push

13
LINKED LIST
IMPLEMENTATION
template <class Object>
class Stack
{
public:
Stack( );
Stack( const Stack & rhs );
~Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
void makeEmpty( );

void pop( );
void push( const Object & x );
Object topAndPop( );
const Object & top( ) const;

const Stack & operator=( const Stack & rhs ); 14


LINKED LIST
IMPLEMENTATION
template <class Object>
class Stack
{
public:
Stack( );
Stack( const Stack & rhs );
~Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
void makeEmpty( );

void pop( );
void push( const Object & x );
Object topAndPop( );
const Object & top( ) const;

const Stack & operator=( const Stack & rhs ); 15


LINKED LIST
IMPLEMENTATION
template <class Object>
class Stack
{
public:
Stack( );
Stack( const Stack & rhs );
~Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
void makeEmpty( );

void pop( );
void push( const Object & x );
Object topAndPop( );
const Object & top( ) const;

const Stack & operator=( const Stack & rhs ); 16


LINKED LIST
IMPLEMENTATION
template <class Object>
class Stack
{
public:
Stack( );
Stack( const Stack & rhs );
~Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
void makeEmpty( );

void pop( );
void push( const Object & x );
Object topAndPop( );
const Object & top( ) const;

const Stack & operator=( const Stack & rhs ); 17


LINKED LIST
IMPLEMENTATION
private:
struct ListNode
{
Object element;
ListNode *next;

ListNode( const Object & theElement, ListNode * n = NULL )


: element( theElement ), next( n ) { }
};

ListNode *topOfStack; // list itself is the stack


};

18
LINKED LIST
IMPLEMENTATION
private:
struct ListNode
{
Object element;
ListNode *next;

ListNode( const Object & theElement, ListNode * n = NULL )


: element( theElement ), next( n ) { }
};

ListNode *topOfStack; // list itself is the stack


};

No need to import the full list class since we only need to do


limited insert and delete. This is a local definition.

19
CONSTRUCTOR

/**
* Construct the stack.
*/
template <class Object>
Stack<Object>::Stack( )
{
topOfStack = NULL;
}

20
isFull

/**
* Test if the stack is logically full.
* Return false always, in this implementation.
*/
template <class Object>
bool Stack<Object>::isFull( ) const
{
return false;
}

21
isEmpty

/**
* Test if the stack is logically empty.
* Return true if empty, false, otherwise.
*/
template <class Object>
bool Stack<Object>::isEmpty( ) const
{
return topOfStack == NULL;
}

22
top

/**
* Get the most recently inserted item in the stack.
* Return the most recently inserted item in the stack
* or throw an exception if empty.
*/
template <class Object>
const Object & Stack<Object>::top( ) const
{
if( isEmpty( ) )
throw Underflow( );
return topOfStack->element;
}

23
pop

/**
* Get the most recently inserted item in the stack.
* Return the most recently inserted item in the stack
* or throw an exception if empty.
*/
template <class Object>
void Stack<Object>::pop( ) const
{
if( isEmpty( ) )
throw Underflow( );
ListNode *oldTop = topOfStack;
topOfStack = topOfStack->next;
delete oldTop;
}

24
push

/**
* Insert x into the stack.
*/
template <class Object>
void Stack<Object>::push( const Object & x )
{
topOfStack = new ListNode( x, topOfStack );
}

25
topAndPop

/**
* Return and remove the most recently inserted item
* from the stack.
*/
template <class Object>
Object Stack<Object>::topAndPop( )
{
Object topItem = top( );
pop( );
return topItem;
}

26
makeEmpty

/**
* Make the stack logically empty.
*/
template <class Object>
void Stack<Object>::makeEmpty( )
{
while( !isEmpty( ) )
pop( );
}

27
Deep Copy
/**
* Deep copy.
*/
template <class Object>
const Stack<Object> & Stack<Object>::
operator=( const Stack<Object> & rhs )
{
if( this != &rhs )
{
makeEmpty( );
if( rhs.isEmpty( ) )
return *this;

ListNode *rptr = rhs.topOfStack;


ListNode *ptr = new ListNode( rptr->element );
topOfStack = ptr;

for( rptr = rptr->next; rptr != NULL; rptr = rptr->next )


ptr = ptr->next = new ListNode( rptr->element );
}
return *this;
28
}
COPY CONSTRUCTOR

/**
* Copy constructor.
*/
template <class Object>
Stack<Object>::Stack( const Stack<Object> & rhs )
{
topOfStack = NULL;
*this = rhs; // deep copy
}

29
DESTRUCTOR

/**
* Destructor.
*/
template <class Object>
Stack<Object>::~Stack( )
{
makeEmpty( );
}

30
LINKED LIST STACKS

• Complexity of operations
• Push
– O(1)
• Pop
– O(1)
• makeEmpty
– O(N) (N is the number of elements)

31
ARRAY IMPLEMENTATION OF
STACKS
• If the maximum size of the stack is known
beforehand, an array implementation of stacks
is possible.

32
ARRAY IMPLEMENTATION OF
STACKS
• If the maximum size of the stack is known
beforehand, an array implementation of stacks
is possible.
– Have an array of objects and
– An index which keeps track of the top of the stack.

33
ARRAY IMPLEMENTATION OF
STACKS
template <class Object>
class Stack
{
public:
Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
const Object & top( ) const;

void makeEmpty( );
void pop( );
void push( const Object & x );
Object topAndPop( );

private:
vector<Object> theArray;
int topOfStack;
}; 34
ARRAY IMPLEMENTATION OF
STACKS
template <class Object>
class Stack
{
public:
Stack( );

bool isEmpty( ) const;


bool isFull( ) const;
const Object & top( ) const;

void makeEmpty( );
void pop( );
void push( const Object & x );
Object topAndPop( );

private:
vector<Object> theArray;
int topOfStack;
}; 35
CONSTRUCTOR
/**
* Construct the stack.
*/
template <class Object>
Stack<Object>::Stack( )
{
topOfStack = -1;
}

36
isEmpty
/**
* Test if the stack is logically empty.
* Return true if empty, false, otherwise.
*/
template <class Object>
bool Stack<Object>::isEmpty( ) const
{
return topOfStack == -1;
}

37
isFull
/**
* Test if the stack is logically full.
* Return true if full, false otherwise.
*/
template <class Object>
bool Stack<Object>::isFull( ) const
{
return topOfStack == theArray.size( ) – 1;
}

38
makeEmpty
/**
* Make the stack logically empty.
*/
template <class Object>
void Stack<Object>::makeEmpty( )
{
topOfStack = –1;
}

39
top
/**
* Get the most recently inserted item in the stack.
* Does not alter the stack.
* Return the most recently inserted item in the stack.
* Exception Underflow if stack is already empty.
*/
template <class Object>
const Object & Stack<Object>::top( ) const
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ topOfStack ];
}

40
pop

/**
* Remove the most recently inserted item from the stack.
* Exception Underflow if stack is already empty.
*/
template <class Object>
void Stack<Object>::pop( )
{
if( isEmpty( ) )
throw Underflow( );
topOfStack ––;
}

41
push

/**
* Insert x into the stack, if not already full.
* Exception Overflow if stack is already full.
*/
template <class Object>
void Stack<Object>::push( const Object & x )
{
if( isFull( ) )
throw Overflow( );
theArray[ ++topOfStack ] = x;
}

42
topAndPop

/**
* Return and remove most recently inserted item from the stack.
* Return most recently inserted item.
* Exception Underflow if stack is already empty.
*/
template <class Object>
Object Stack<Object>::topAndPop( )
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ topOfStack –– ];
}

43
ARRAY-BASED STACKS

• Complexity of operations
• Push
– O(1)
• Pop
– O(1)
• makeEmpty
– O(1)
• Array based stacks are VERY efficient.
44
USING STACKS

• Checking for balanced parenthesis

45
USING STACKS

• Checking for balanced parenthesis


– ( ( ) ( ( ) ) ( ) ( ) ( ( ) ) ) – Parenthesis balanced
– ( ) ( ) ( ) ) – Parenthesis not balanced

46
USING STACKS

• Checking for balanced parenthesis


– ( ( ) ( ( ) ) ( ) ( ) ( ( ) ) ) – Parenthesis balanced
– ( ) ( ) ( ) ) – Parenthesis not balanced
• Idea
– When you see a (, push it onto the stack
– When you see a ), check if the top of the stack is a (,
if so pop, if not then unbalanced
– If stack is empty when input is finished then
balanced.
47
CHECKING PARENTHESIS
Stack Remaining Input

(()(()))

48
CHECKING PARENTHESIS
Stack Remaining Input

()(()))

49
CHECKING PARENTHESIS
Stack Remaining Input

)(()))

(
(

50
CHECKING PARENTHESIS
Stack Remaining Input

)(()))

(
(

51
CHECKING PARENTHESIS
Stack Remaining Input

(()))

52
CHECKING PARENTHESIS
Stack Remaining Input

()))

(
(

53
CHECKING PARENTHESIS
Stack Remaining Input

)))

(
(
(

54
CHECKING PARENTHESIS
Stack Remaining Input

))

(
(

55
CHECKING PARENTHESIS
Stack Remaining Input

56
CHECKING PARENTHESIS
Stack Remaining Input

Stack is empty when input is finished - BALANCED

57
CHECKING PARENTHESIS
Stack Remaining Input

(()

58
CHECKING PARENTHESIS
Stack Remaining Input

()

59
CHECKING PARENTHESIS
Stack Remaining Input

(
(

60
CHECKING PARENTHESIS
Stack Remaining Input

Stack is not empty when input is finished

NOT BALANCED

61
CHECKING PARENTHESIS
Stack Remaining Input

)(

Stack does not have a matching ( on top

NOT BALANCED

62
CHECKING PARENTHESIS
#define OPEN ‘(‘
#define CLOSED ‘)’
void main () {
Stack<char> symbolStack; // Stack of characters
char symbol;
cin >> symbol;
while (symbol != '*') {
if (symbol == OPEN) symbolStack.push(OPEN); // push ( on top the stack
else
{
if (symbolStack.isEmpty())
{
cout << "Unbalanced Parenthesis " << endl;
break;
}

symbolStack.pop(); // pop ( from the stack


}
cin >> symbol;
}

...

63
CHECKING PARENTHESIS

if (symbol == '*') {
if (! symbolStack.isEmpty())
cout << "Unbalanced Parenthesis " << endl;
else
cout << "Balanced Parenthesis " << endl;
}

64
POSTFIX EXPRESSIONS

• A * B + C * D is an infix arithmetic expression

65
POSTFIX EXPRESSIONS

• A * B + C * D is an infix arithmetic expression


– Operators are in-between the operands
– Possibly ambiguous

66
POSTFIX EXPRESSIONS

• A B * C D * + is a postfix arithmetic expression


– Operators follow operands
– Each operator applies to two previous operands or
results
– Postfix expressions can easily be evaluated using
stacks

67
EVALUATING POSTFIX EXP.

• If the next input is an operand push onto the


stack
• If the next input is an operator
– Pop the last two operands from the stack
– Apply the operator
– Push the result onto the stack

68
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)

69
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)

70
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)
– Pop 3 and 4, multiply and push 12 back: Stack is
(12)

71
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)
– Pop 3 and 4, multiply and push 12 back: Stack is
(12)
– Push 5 Stack is (12,5)

72
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)
– Pop 3 and 4, multiply and push 12 back: Stack is
(12)
– Push 5 Stack is (12,5)
– Push 6 Stack is (12,5,6)

73
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)
– Pop 3 and 4, multiply and push 12 back: Stack is
(12)
– Push 5 Stack is (12,5)
– Push 6 Stack is (12,5,6)
– Pop 5 and 6, multiply and push 30 back: (Stack is
(12,30)
74
EVALUATING POSTFIX EXP.

• 34*5 6*+
– Push 3 Stack is (3)
– Push 4 Stack is (3,4)
– Pop 3 and 4, multiply and push 12 back: Stack is (12)
– Push 5 Stack is (12,5)
– Push 6 Stack is (12,5,6)
– Pop 5 and 6 add and push 11 back: (Stack is (12,30)
– Pop 12 and 30, add and push 42: Stack is (42)

75
INFIX TO POSTFIX

• Stacks can also be used for converting an infix


expression to a postfix expression.
• See the textbook for further info.

76
OTHER USES OF STACKS

• Stacks are heavily used in operations


– on binary trees
– on graphs
– Other operations that involve “recursion” of some
sort.

77
QUEUES

• Insert (enqueue) at the back


• Remove (dequeue) from front

78
QUEUES

• Insert (enqueue) at the back


• Remove (dequeue) from front
• Possible implementations
– Maximum queue size is known
• Array-based implementation

79
QUEUES

• Insert (enqueue) at the back


• Remove (dequeue) from front
• Possible implementations
– Maximum queue size is known
• Array-based implementation
– Maximum queue size is not known
• Use linked list implementation

80
QUEUES

• Linked list implementation.


– Standard linked list with an additional pointer to the
last element of the lists

81
QUEUES

• Linked list implementation.


– Standard linked list with an additional pointer to the
last element of the lists

Front
Back

82
QUEUES

• Linked list implementation.


– Standard linked list with an additional pointer to the
last element of the lists

Front
Back

Delete elements from here Insert new elements here

83
QUEUES
• Array implementation
• Keep
– an array of objects

84
QUEUES
• Array implementation
• Keep
– an array of objects
– indexes for front and back positions
– current number of elements

85
QUEUES
template <class Object>
class Queue
{
public:
Queue(int size);
bool isEmpty( ) const;
bool isFull( ) const;
const Object & getFront( ) const;

void makeEmpty( );
Object dequeue( );
void enqueue( const Object & x );

private:
vector<Object> theArray;
int currentSize;
int front;
int back;

void increment( int & x );


}; 86
QUEUES
template <class Object>
class Queue
{
public:
Queue(int size);
bool isEmpty( ) const;
bool isFull( ) const;
const Object & getFront( ) const;

void makeEmpty( );
Object dequeue( );
void enqueue( const Object & x );

private:
vector<Object> theArray;
int currentSize;
int front;
int back;

void increment( int & x );


}; 87
QUEUES

• To enqueue an element X
– Increment currentSize and back
– Set theArray[back] = X

88
QUEUES

• To enqueue an element X
– Increment currentSize and back
– Set theArray[back] = X
• To dequeue an element
– Set return value = theArray[front]
– Decrement currentSize
– Increment front
• The increments are circular.

89
QUEUES

• To enqueue an element X
– Increment currentSize and back
– Set theArray[back] = X
• To dequeue an element
– Set return value = theArray[front]
– Decrement currentSize
– Increment front
• The increments are circular.

90
QUEUES
0 1 2 3 4 5

Initial State
currSize = 0

Back Front

91
QUEUES
0 1 2 3 4 5

Initial State
currSize = 0

Back Front

0 1 2 3 4 5

3 Enqueue(3)
currSize = 1

Front

Back

92
QUEUES
0 1 2 3 4 5

Enqueue(4)
3 4
currSize = 2

Front Back

0 1 2 3 4 5

3 4 5 Enqueue(5)
currSize = 3

Front Back

93
QUEUES
After 3 more enqueues

0 1 2 3 4 5

3 4 5 6 7 8 Enqueue(8)
currSize = 6

Front Back

94
QUEUES
0 1 2 3 4 5

3 4 5 6 7 8 Dequeue returns 3
currSize = 5

Front Back

0 1 2 3 4 5

3 4 5 6 7 8 Dequeue returns 4
currSize = 4

Front Back

95
QUEUES
0 1 2 3 4 5

9 4 5 6 7 8 Enqueue (9)
currSize = 5

Back Front

0 1 2 3 4 5

9 10 5 6 7 8 Enqueue (10)
currSize = 6

Back Front

96
QUEUES
0 1 2 3 4 5

9 10 5 6 7 8 Dequeue returns 5
currSize = 5

Back Front

0 1 2 3 4 5

9 10 5 6 7 8 Dequeue returns 6
currSize = 4

Back Front

97
makeEmpty

/**
* Make the queue logically empty.
*/
template <class Object>
void Queue<Object>::makeEmpty( )
{
currentSize = 0;
front = 0;
back = -1;
}

98
CONSTRUCTOR

/**
* Construct the queue.
*/
template <class Object>
Queue<Object>::Queue(int size):theArray(size) {
makeEmpty( );
}

99
isEmpty

/**
* Test if the queue is logically empty.
* Return true if empty, false, otherwise.
*/
template <class Object>
bool Queue<Object>::isEmpty( ) const
{
return currentSize == 0;
}

100
isFull

/**
* Test if the queue is logically full.
* Return true if full, false, otherwise.
*/
template <class Object>
bool Queue<Object>::isFull( ) const
{
return currentSize == theArray.size( );
}

101
getFront

/**
* Get the least recently inserted item in the queue.
* Return the least recently inserted item in the
* queue or throw Underflow if empty.
* */
template <class Object>
const Object & Queue<Object>::getFront( ) const
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ front ];
}

102
dequeue

/*** Return and remove the least recently inserted


* item from the queue. Throw Underflow if empty.
*/
template <class Object>
Object Queue<Object>::dequeue( )
{
if( isEmpty( ) )
throw Underflow( );
currentSize--;
Object frontItem = theArray[ front ];
increment( front );
return frontItem;
}
103
enqueue

/**
* Insert x into the queue.
* Throw Overflow if queue is full.
*/
template <class Object>
void Queue<Object>::enqueue( const Object & x )
{
if( isFull( ) )
throw Overflow( );
increment( back );
theArray[ back ] = x;
currentSize++;
}
104
increment

/**
* Internal method to increment x with
* wraparound.
*/
template <class Object>
void Queue<Object>::increment( int & x )
{
if( ++x == theArray.size( ) )
x = 0;
}

105
USES OF QUEUES
• Not as popular as lists and stacks
• Used in applications where a real life queue situation
exists
– Printer management requires that print requests be queued
and serviced in order
– Operating systems services queue disk access requests from
programs and service them in order
– Simulation of actual queues
• Some applications in implementing other data
structures

106

You might also like