0% found this document useful (0 votes)
2 views

lecture#3

The document provides an introduction to the Stack and Queue Abstract Data Types (ADTs), detailing their structures, operations, and implementations. It covers both static and dynamic implementations of stacks and queues, including array and linked list approaches, as well as their respective operations like push, pop, enqueue, and dequeue. Additionally, it discusses the Standard Template Library (STL) implementations for stacks and queues, and the benefits of eliminating recursion in favor of iterative solutions.

Uploaded by

Medo Medo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

lecture#3

The document provides an introduction to the Stack and Queue Abstract Data Types (ADTs), detailing their structures, operations, and implementations. It covers both static and dynamic implementations of stacks and queues, including array and linked list approaches, as well as their respective operations like push, pop, enqueue, and dequeue. Additionally, it discusses the Standard Template Library (STL) implementations for stacks and queues, and the benefits of eliminating recursion in favor of iterative solutions.

Uploaded by

Medo Medo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

Introduction to the Stack ADT

Stack: a LIFO (last in, first out) data structure


Examples:
◦ plates in a cafeteria serving area
◦ return addresses for function calls

18-2
Stack Basics

Stack is usually implemented as a list, with additions and removals taking


place at one end of the list
The active end of the list implementing the stack is the top of the stack
Stack types:
◦ Static – fixed size, often implemented using an array
◦ Dynamic – size varies as needed, often implemented using a linked list

18-3
Stack Operations and Functions
Operations:
◦ push: add a value at the top of the stack
◦ pop: remove a value from the top of the stack

Functions:
◦ isEmpty: true if the stack currently contains no elements
◦ isFull: true if the stack is full; only useful for static stacks

18-4
Static Stack Implementation
Uses an array of a fixed size
Bottom of stack is at index 0. A variable called top tracks the current top of the stack
const int STACK_SIZE = 3;
char s[STACK_SIZE];
int top = 0;

top is where the next item will be added

18-5
Array Implementation Example
This stack has max capacity 3, initially top = 0 and stack is empty.

K K
push('E'); push('K'); push('G');
E E E
top is 1 top is 2 top is 3

18-6
Stack Operations Example

After three pops, top == 0 and the stack is empty

K
pop(); pop(); pop();
(remove G) E (remove K) E (remove E)

18-7
Array Implementation
char s[STACK_SIZE];
int top=0;
To check if stack is empty:
bool isEmpty()
{
if (top == 0)
return true;
else return false;
}

18-8
Array Implementation
char s[STACK_SIZE];
int top=0;
To check if stack is full:
bool isFull()
{
if (top == STACK_SIZE)
return true;
else return false;
}

18-9
Array Implementation
To add an item to the stack
void push(char x)
{
if (isFull())
{error(); exit(1);}
// or could throw an exception
s[top] = x;
top++;
}

18-10
Array Implementation
To remove an item from the stack
void pop(char &x)
{
if (isEmpty())
{error(); exit(1);}
// or could throw an exception
top--;
x = s[top];
}

18-11
Class Implementation
class STACK
{
private:
char *s;
int capacity, top;
public:
void push(char x);
void pop(char &x);
bool isFull(); bool isEmpty();
STACK(int stackSize);
~STACK()
};

18-12
Exceptions from Stack Operations
Exception classes can be added to stack object definition to handle cases where an attempt is
made to push onto a full stack (overflow) or to pop from an empty stack (underflow)
Program that uses push and pop operations should do so from within a try block.
catch block(s) should follow the try block, interpret what occurred, and inform the user.

18-13
Dynamic Stacks
Implemented as a linked list
Can grow and shrink as necessary
Can't ever be full as long as memory is available

18-14
Linked List Implementation
Node for the linked list
struct LNode
{
char value;
LNode *next;
LNode(char ch, LNode *p = 0)
{ value = ch; next = p;}
};
Pointer to beginning of linked list, which will serve as top of stack
LNode *top = NULL;

18-15
Linked List Implementation
A linked stack after three push operations:
push('a'); push('b'); push('c');

c b a NULL

top

18-16
Operations on a Linked Stack
Check if stack is empty:
bool isEmpty()
{
if (top == NULL)
return true;
else
return false;
}

18-17
Operations on a Linked Stack
Add a new item to the stack
void push(char x)
{
top = new LNode(x, top);
}

18-18
Operations on a Linked Stack
Remove an item from the stack
void pop(char &x)
{
if (isEmpty())
{ error(); exit(1);}
x = top->value;
LNode *oldTop = top;
top = top->next;
delete oldTop;
}

18-19
The STL stack Container
Stack template can be implemented as a vector, list, or a deque
Implements push, pop, and empty member functions
Implements other member functions:
◦ size: number of elements on the stack
◦ top: reference to element on top of the stack (must be used with pop to remove and retrieve top
element)

18-20
Defining an STL-based Stack
Defining a stack of char, named cstack, implemented using a vector:
stack< char, vector<char> > cstack;

Implemented using a list:


stack< char, list<char> > cstack;

Implemented using a deque (default):


stack< char > cstack;

Spaces are required between consecutive > > symbols to distinguish from
stream extraction

18-21
Introduction to the Queue ADT
Queue: a FIFO (first in, first out) data structure.
Examples:
◦ people in line at the theatre box office
◦ print jobs sent to a printer
Implementation:
◦ static: fixed size, implemented as array
◦ dynamic: variable size, implemented as linked list

18-22
Queue Locations and Operations
rear: position where elements are added
front: position from which elements are removed
enqueue: add an element to the rear of the queue
dequeue: remove an element from the front of a queue

18-23
Array Implementation of Queue

An empty queue that can hold char values:

enqueue('E');
front, rear

front rear

18-24
Queue Operations - Example
enqueue('K');

E K

front
enqueue('G'); rear

E K G

front rear

18-25
Queue Operations - Example
dequeue(); // remove E

K G

front// rear
dequeue(); remove K

front rear

18-26
Array Implementation Issues

In the preceding example, Front never moves.


Whenever dequeue is called, all remaining queue entries move up one position. This takes
time.
Alternate approach:
◦ Circular array: front and rear both move when items are added and removed. Both can ‘wrap
around’ from the end of the array to the front if warranted.

Other conventions are possible

18-27
Array Implementation Issues
Variables needed
◦ const int QSIZE = 100;
◦ char q[QSIZE];
◦ int front = -1;
◦ int rear = -1;
◦ int number = 0; //how many in queue

Could make these members of a queue class, and queue operations would be
member functions

18-28
isEmpty Member Function
Check if queue is empty
bool isEmpty()
{
if (number > 0)
return false;
else
return true;
}

18-29
isFull Member Function
Check if queue is full
bool isFull()
{
if (number < QSIZE)
return false;
else
return true;
}

18-30
enqueue and dequeue

To enqueue, we need to add an item x to the rear of the queue


Queue convention says q[rear] is already occupied. Execute
if(!isFull)
{ rear = (rear + 1) % QSIZE;
// mod operator for wrap-around
q[rear] = x;
number ++;
}

18-31
enqueue and dequeue

To dequeue, we need to remove an item x from the front of the queue


Queue convention says q[front] has already been removed. Execute
if(!isEmpty)
{ front = (front + 1) % QSIZE;
x = q[front];
number--;
}

18-32
enqueue and dequeue
enqueue moves rear to the right as it fills positions in the array
dequeue moves front to the right as it empties positions in the array
When enqueue gets to the end, it wraps around to the beginning to use those positions that
have been emptied
When dequeue gets to the end, it wraps around to the beginning use those positions that have
been filled

18-33
enqueue and dequeue
Enqueue wraps around by executing
rear = (rear + 1) % QSIZE;
Dequeue wraps around by executing
front = (front + 1) % QSIZE;

18-34
Dynamic Queues
Like a stack, a queue can be implemented using a linked list
Allows dynamic sizing, avoids issue of wrapping indices

NULL

front rear

18-35
Dynamic Queue Implementation Data
Structures
struct QNode
{
char value;
QNode *next;
QNode(char ch, QNode *p = NULL);
{value = ch; next = p;}
}
QNode *front = NULL;
QNode *rear = NULL;

18-36
isEmpty Member Function
To check if queue is empty:
bool isEmpty()
{
if (front == NULL)
return true;
else
return false;
}

18-37
enqueue Member Function
To add item at rear of queue
void enqueue(char x)
{
if (isEmpty())
{ rear = new QNode(x);
front = rear;
return;
}
rear->next = new QNode(x);
rear = rear->next;
}

18-38
dequeue Member Function
To remove item from front of queue
void dequeue(char &x)
{
if (isEmpty())
{ error(); exit(1);
}
x = front->value;
QNode *oldfront = front;
front = front->next;
delete oldfront;
}

18-39
The STL deque and queue Containers
deque: a double-ended queue. Has member functions to enqueue
(push_back) and dequeue (pop_front)

queue: container ADT that can be used to provide a queue based on a


vector, list, or deque. Has member functions to enqueue (push) and
dequeue (pop)

18-40
Defining a Queue
Defining a queue of char, named cQueue, based on a deque:
deque<char> cQueue;

Defining a queue with the default base container


queue<char> cQueue;

Defining a queue based on a list:


queue<char, list<char> > cQueue;

Spaces are required between consecutive > > symbols to distinguish from
stream extraction

18-41
Eliminating Recursion
Recursive solutions to problems are often elegant but inefficient
A solution that does not use recursion is more efficient for larger sizes of inputs
Eliminating the recursion: re-writing a recursive algorithm so that it uses other programming
constructs (stacks, loops) rather than recursive calls

You might also like