0% found this document useful (0 votes)
87 views32 pages

Stacks and Queues: Saurav Karmakar Spring 2007

The document discusses stacks and queues, which are linear data structures that operate based on LIFO (last in first out) and FIFO (first in first out) principles respectively. Stacks can be implemented using arrays or linked lists, while queues support two main operations: enqueue to add an item and dequeue to remove an item. The document provides code examples to demonstrate vector-based implementations of stacks and queues in C++ using arrays, with adjustments like doubling the array size as needed and wrapping elements to reuse space.

Uploaded by

mb08026
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
87 views32 pages

Stacks and Queues: Saurav Karmakar Spring 2007

The document discusses stacks and queues, which are linear data structures that operate based on LIFO (last in first out) and FIFO (first in first out) principles respectively. Stacks can be implemented using arrays or linked lists, while queues support two main operations: enqueue to add an item and dequeue to remove an item. The document provides code examples to demonstrate vector-based implementations of stacks and queues in C++ using arrays, with adjustments like doubling the array size as needed and wrapping elements to reuse space.

Uploaded by

mb08026
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 32

Chapter 16

Stacks and Queues

Saurav Karmakar
Spring 2007
Objective
 In this chapter we will learn:
 Stacks
 Queues
 Different implementations (arrays and
linked list) of both
 Comparison of implementation
Stack
 A stack is a data structure that
works on the principle of
Last In First Out (LIFO).

 So last item put on the stack is


the first item that can be taken
off, like a physical stack of
books/plates.

 In stack new elements are


added to and removed from the
top of the structure.
Two Implementations of Stack

 As Vector
Storing the items contiguously .

 As List
Storing items noncontiguously.
Stack
 Can be implemented with an array and
an integer that indicates the top
element of the stack (tos).

 Empty stack : tos = -1.

 Basic Operations : PUSH and POP.


How stack works
Empty stack push(a) push(b) pop(b)

tos=1 b

tos=0 a a
tos=0
a

tos= -1
Stack – Vector Implementation
template <class Object>
A stack can be implemented with class Stack{
an vector and an integer that {
indicates the index of the top public:
element. Stack( );
//construct the stack bool isEmpty( ) const;
Template <class Object> const Object & top( ) const;
Stack<Object>::Stack():the Array(1){ void makeEmpty( );
topOfStack = -1; void pop( );
} void push( const Object & x );
//test if the stack is logically empty Object topAndPop( );
Template <class Object> private:
Stack<Object>::isEmpty() const{ vector<Object> theArray;
return topOfStack == -1; int topOfStack;
} };
The push/pop function (vector-based)
template <class Object>
void Stack<Object>::push( const Object & x )
{
if( topOfStack == theArray.size( ) - 1 )
theArray.resize( theArray.size( ) * 2 + 1 );
theArray[ ++topOfStack ] = x;
} // If there is no vector doubling, push takes constant time, otherwise it
// takes O(N) time. But it does not happen often.

template <class Object>


void Stack<Object>::pop( const Object & x )
{
if( isEmpty())
throw UnderflowException();
topOfStack--;
}
Linked List Implementation

 Advantage of the linked list : using


only one pointer per item at a time.

 Disadvantage of contiguous vector


implementation : using excess space
equal to the number of vacant array
items .
Linked List
Implementation of Stack
 The stack class can be implemented as a
linked list in which the top of the stack is
represented by the first item in the list.

topOfStack
Linked List
Implementation of Stack
 Each stack item stores
 element value
 pointer to next element
Application of Stack

 Recognizing palindromes
 Checking balanced expressions
 Evaluating algebraic expressions is easier.
 Searching networks, traversing trees
(keeping a track where we are).
Infix to Postfix Conversion
 Scan the Infix string from left to right.
 Initialise an empty stack.
 If the scannned character is an operand, add it to the Postfix string.
 If the scanned character is an operator and if the stack is empty Push
the character to stack.
 If the scanned character is an Operator and the stack is not
empty, compare the precedence of the character with the
element on top of the stack (topStack).
If topStack has higher precedence over the scanned
character Pop the stack
else Push the scanned character to stack.
Repeat this step as long as stack is not empty and topStack has
precedence over the character.
 Repeat this step till all the characters are scanned.
 (After all characters are scanned, we have to add any character that the
stack may have to the Postfix string.) If stack is not empty add topStack
to Postfix string and Pop the stack.
 Repeat this step as long as stack is not empty.
 Return the Postfix string.
Example : String a+b*c-d
              STACK                      PostfixString
Postfix Expression Evaluation
for each character C in a given string
{
if C is an operand
push C onto stack;
else // C is an operator
{
pop item from stack, and store in Opr2;
pop item from stack, and store in Opr1;
result = Opr1 C Opr2, using C as an operator;
push result onto stack;
}
}
QUEUE
 A queue is an abstract
data struture where
various entities such as
data, objects, persons, or
events are stored and
waiting to be processed.

 The most well known


operation of the queue is
the First-In-First-Out
(FIFO) queue process .

 In a FIFO queue, the first


element in the queue will
be the first one out
Queue
 Can be implemented using
 Vector/Array
 Link List

 Two main Operations :


 Enqueue
 Dequeue
Queue:
Vector/Array Implementation

 Store items in an vector/array with front


item at index zero and back item at index
Back.
 Enqueue is easy: increment Back.
 Dequeue is inefficient: all elements have
to be shifted. (If use only one index)

Result: Dequeue will be O (N ).
Queue
Step 1. makeEmpty()

Back
Step 4. dequeue()

Step 2. enqueue() Back


Back

a b
Step 3. enqueue() After dequeue() :
Back Back

a b b
Better Idea
 Keep a Front index.
 To Dequeue, increment Front. Therefore,
Dequeue takes constant time now.

a b c d

Front Back

a b c d

Front Back
Queue
Step 1. makeEmpty()
Step 4. dequeue()
Back
Back

Front
Step 2. enqueue() b
Back

Front
a
After dequeue() :
Front Step 3. enqueue()
Back
Back

a b b
Front Front
Circular Implementation

 Previous implementation is O( 1 ) per


operation.
 However, after vector.size() times
enqueues, we are full, even if queue is
logically nearly empty for dequeue
opeartions on the elements.
 Solution: use wraparound to reuse the cells
at the start of the vector. To increment, add
one, but if that goes past end, reset to zero.
Problem with the approach :
Back

c d
Front

Solution : Recycle / Wrap Around


Back

e c d

Front
Circular Example
 Both Front and Back wraparound as
needed.
b c d e f

Front Back

g b c d e f

Back Front
QUEUE--Vector Implementation
 Mostly straightforward; maintain
 Front

 Back

 CurrentSize: Current number of items in queue

 Only tricky part is vector doubling because the queue


items are not necessarily stored in an array starting
at location 0, and the contiguity of wraparound must
be maintained.
Queue – Vector Implementation
Template <class Object> template <class Object>
Class Queue{ void Queue<Object>::enqueue(const Object & x){
public: if(currentSize == theArray.size())
Queue(); doubleQueue();
bool isEmpty() const; increment( back);
const Object & getFront() const; theArray[back] = x;
void makeEmpty(); currentSize++;
Object dequeue(); }
void enqueue (const Ojbect & x); template <class Object>
private: void Queue<Object>::doubleQueue() {
vector<Object> theArray; theArray.resize(theArray.size() * 2 + 1);
int currentSize; if(front != 0){
int front; for(int i=0; i<front; i++){
int back; theArray[i+currentSize] = theArray[i];
void increment (int & x) const; back += currentSize;
void doubleQueue(); }
} }
Queue – Vector Implementation cont.
template <class Object> template <class Object>
Object Queue<Object>::dequeue() {
const Object & Queue<Object>::getFront() const {
if( isEmpty())
if (isEmpty()) throw UnderflowException();
throw UnderflowException(); currentSize--;
return theArray[front]; Object frontItem = theArray[front];
increment(front);
}
return frontItem;
}
template <class Object>
void Queue<Object>::makeEmpty(){
currentSize = 0;
front = 0;
back = theArray.size() –1;
}
Linked List Implementation

 Advantage of the linked list is excess


memory is only one pointer per item.

 In contrast, a contiguous vector


implementation uses excess space.
Queue
 Same idea as like STACK, but has front
and back

front back
Comparison of the Two Methods

 Both of them run in constant time per


operation.
 The vector version is likely to be faster.
But it has two drawbacks:
 The wraparound is a little confusing;
 It might waste more space.
Deque/Double-Ended Queue
 A deque is a double-ended queue.
 A deque is a little modification on the queue
data structure, where access is given to both
the ends.
 Operations : addFront, addRear,
removeFront, removeRear.
 That is, a deque is especially optimized for
pushing and popping elements at the
beginning and end. As with vectors, storage
management is handled automatically.
Common errors (Page 561)
 Do not delete the top node directly
before adjusting the top of the stack
pointer
 Be aware of memory leaks
 Access is constant time in both of these
implementations.

You might also like