Stacks and Queues All Lahcen
Stacks and Queues All Lahcen
intro
PUSH( )
top Objects can only be removed the top of the stack.
top
The operation to remove an object from a stack is called POP
POP()
top The top of the stack element is the only element that can be accessed
PEEK( )
top
The final operation is ISEMPTHY(), which returns true if
the the stack empty and false otherwise.
ISEMPTY( )
top A Stack is linear data structure with constraints on how
data is accessed, inserted and removed in it.
• You can only insert, remove or access the element stored
at the top of the stack
top Stacks stack data structure has a number of applications
• Verification of pairs of element such as parenthesis.
• Undoing actions in inverse chronological order
1st application
Verification of pairs of elements such
class Node
{
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
For example: When your compiler alerts that there is a missing closing bracket in your code
The compiler may use a stack to carry on the parenthesis varication task.
class Node No parenthesis here
{
public:
int data; • Every time an opening bracket is found
shared_ptr<Node> next;
an element is pushed in the stack
Node(int d) { • Every time a closing bracket is found
data = d; and element is removed from the stack
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{ Opening parenthesis found, PUSH
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
top
PUSH( )
class Node
{
public: No parenthesis here
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{
public:
int data; No parenthesis here
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{
public:
int data;
shared_ptr<Node> next; No parenthesis here
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{
public:
int data;
shared_ptr<Node> next;
No parenthesis here
Node(int d) {
data = d;
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{
public:
int data;
shared_ptr<Node> next;
top
PUSH( )
class Node
{
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d; No parenthesis here
next = nullptr;
}
//error due to missing parenthesis here
top
class Node
{
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr; No parenthesis here
}
//error due to missing parenthesis here
top
class Node
{
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
} Closing parenthesis found, POP()
//error due to missing parenthesis here
top
POP(
)
class Node
{
public:
int data;
shared_ptr<Node> next;
Node(int d) {
data = d;
next = nullptr;
}
No parenthesis here
top
class Node
{
public:
ISEMPTY() is executed at the end!
int data; • If it returns true then brackets are balanced
shared_ptr<Node> next; • If if returns false, then there is a missing parenthesis
Node(int d) {
data = d;
next = nullptr; In this case it will return false to signal there is a
} missing closing bracket.
top
ISEMPTY( )
2nd application of stacks: undoing action in reverse chronological order.
top ACTION 1
ACTION 1 ACTION 2
top ACTION 2
ACTION 1
ACTION 1 ACTION 2 ACTION 3 ACTION 4 ACTION 5
top ACTION 5
ACTION 4
ACTION 3
ACTION 2
ACTION 1
ACTION 1 ACTION 2 ACTION 3 ACTION 4 ACTION 5
UNDO
top ACTION 5
ACTION 4
ACTION 3
ACTION 2
ACTION 1
ACTION 1 ACTION 2 ACTION 3 ACTION 4
N 5
TIO
AC
top ACTION 4
ACTION 3
ACTION 2
ACTION 1
POP(
ACTION 1 ACTION 2 ACTION 3
ION4
ACT
top ACTION 3
ACTION 2
ACTION 1
POP(
Summary:
Stack
• Stack definition
top • Stack operations
• Stack applications
• Next, we will look at how to implement a
stack data structure.
Stacks
implementation
top 0x9
top 0x9
top 0x9
top
Array implementation
top
top
top
top
function PUSH(x)
top=top+1
[0] [1] [2] [3] [4]
A[top]=x
top
STACK
top
function PUSH(x)
top=top+1
[0] [1] [2] [3] [4]
A[top]=x
top
STACK
top
function PUSH(x)
top=top+1 C0
[0] [1] [2] [3] [4]
A[top]=x C1
top
top
function PUSH(x)
[0] [1] [2] [3] [4] top=top+1
A[top]=x
top
What if we run out of space in the array?
STACK
top
function PUSH(x)
[0] [1] [2] [3] [4] top=top+1
A[top]=x
top
This instruction will return an error! There are two ways of solving this problem !
STACK
top
function PUSH(x)
[0] [1] [2] [3] [4] if(top==size(A)-1)
print(“stack overflow”)
top return
top=top+1
A[top]=x
STACK
top
function PUSH(x)
[0] [1] [2] [3] [4] if(top==size(A)-1)
extend©
top top=top+1
A[top]=x
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
top
function POP( )
[0] [1] [2] [3] [4]
top
We assume that POP() doesn’t return the element removed.
STACK
top
function POP( )
top=top-1
[0] [1] [2] [3] [4]
top
To delete an element of the top we only need to decrease the value of the variable top by
STACK
top
function POP( )
if (top==-1)
[0] [1] [2] [3] [4]
print(“empty stack”)
top return
top=top-1
Checks if the stack is empty
STACK
top
function POP( )
C0 if (top==-1)
[0] [1] [2] [3] [4]
C1 print(“empty stack”)
top C2 return
top=top-1
C3
top
function PEEK( )
if (top==-1)
[0] [1] [2] [3] [4]
print(“empty stack”)
top return
return A[top]
STACK
top
function PEEK( )
C0 if (top==-1)
[0] [1] [2] [3] [4]
C1 print(“empty stack”)
top C2 return
return A[top]
C3
top
function ISEMPTY( )
if (top==-1)
[0] [1] [2] [3] [4]
return TRUE
top return FALSE
STACK
top
function ISEMPTY( )
C0 if (top==-1)
[0] [1] [2] [3] [4]
C1 return TRUE
top C2 return FALSE
top
TIME COMPLEXITY
OPERATION BEST CASE WORST CASE
PUSH Θ(1) Θ(N)
POP Θ(1) Θ(1)
PEEK Θ(1) Θ(1)
ISEMPTY Θ(1) Θ(1)
STACK
top
top 0x9
top
top
NULL
STACK
top
0x16 NULL
STACK
top
0x16 NULL
STACK
top
0x16 NULL
top
function POP( )
top 0xE
0x16 NULL
top
function POP( )
top 0xE if(top==NULL)
print(“empty list”)
return
0x16 NULL top=top->next
STACK
top
function POP( )
top 0xE if(top==NULL)
print(“empty list”)
return
0x16 NULL top=top->next
STACK
top
function POP( )
top 0xE if(top==NULL)
print(“empty list”)
return
0x16 NULL top=top->next
STACK
top
function POP( )
top 0xE if(top==NULL)
print(“empty list”)
return
NULL top=top->next
STACK
top
function POP( )
top 0xE C0 if(top==NULL)
C1 print(“empty list”)
C2 return
NULL top=top->next
C3
top
function PEEK( )
top 0xE if(top==NULL)
print(“empty list”)
return
NULL print(top->data)
STACK
top
function PEEK( )
top 0xE if(top==NULL)
print(“empty list”)
return
NULL print(top->data)
STACK
top
function PEEK( )
top 0xE if(top==NULL)
print(“empty list”)
return
NULL print(top->data)
STACK
top
function PEEK( )
top 0xE C0 if(top==NULL)
C1 print(“empty list”)
C2 return
NULL print(top->data)
C3
top
function ISEMPTY( )
top 0xE if(top==NULL)
return TRUE
return FALSE
NULL
STACK
top
function ISEMPTY( )
top 0xE C0 if(top==NULL)
C1 return TRUE
C2 return FALSE
NULL
A queue data structure works in the same way as a queue in real life
tail
front
ENQUEUE( )
DEQUEUE( )
PEEK( )
If you want to know the content of the queue, you can only at the front of queue
• this operation is call PEEK()
• PEEK() return the value of the element at the front of the queue.
front tail
ISEMPTY( )
front tail
A queue a data structure were elements are inserted in one end and
removed from the the other end.
One application of queue
front tail
Processes
Array implementation
• We first create an array
• initialise front and tail to -1
front
tail
front tail
Array implementation
To enqueue one element into the list:
We first need to check if the queue is empty
[0] [1] [2] [3] [4]
front
tail
front tail
Array implementation
If the queue is empty:
• Update tail to point 0
front
tail
front tail
Array implementation
If the queue is empty:
• Update tail to point 0
• Update front to point 0
[0] [1] [2] [3] [4]
front
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
front
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
A[tail]=x
[0] [1] [2] [3] [4]
front
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
A[tail]=x
[0] [1] [2] [3] [4]
front
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
A[tail]=x
[0] [1] [2] [3] [4] else
tail=tail+1
front
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
A[tail]=x
[0] [1] [2] [3] [4] else
tail=tail+1
front A[tail]=x
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
A[tail]=x
[0] [1] [2] [3] [4] else
tail=tail+1
front A[tail]=x
tail
front tail
function ENQUEUE(x)
if (ISEMPTY())
Array implementation front=0
tail=0
else
[0] [1] [2] [3] [4] tail=tail+1
A[tail]=x
front
tail
front tail
Array implementation
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
front=front+1
[0] [1] [2] [3] [4]
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
front=front+1
[0] [1] [2] [3] [4]
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
front=front+1
[0] [1] [2] [3] [4]
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
front=front+1
[0] [1] [2] [3] [4]
front
tail
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4] front=-1
tail=-1
front else
tail front=front+1
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4] front=-1
tail=-1
front else
tail front=front+1
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4] front=-1
tail=-1
front else
tail front=front+1
front tail
function DEQUEUE()
if (ISEMPTY())
Array implementation print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4] front=-1
tail=-1
front else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
front tail=-1
else
tail front=front+1
front tail
function ENQUEUE(x)
if (ISEMPTY())
front=0
tail=0
else
tail=tail+1
A[tail]=x
function DEQUEUE()
Array implementation if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
[0] [1] [2] [3] [4]
front=-1
Available &
unreachable front tail=-1
else
tail front=front+1
We need both pointer to traverse the array in a circular way
Once front or tail reach the end of the array, they should
function ENQUEUE(x) be able to jump to the first position array.
if (ISEMPTY())
front=0
tail=0
else
tail=(tail+1)%N
A[tail]=x
Array implementation
front
tail
We also need to check if the queue is full
function ENQUEUE(x)
if((tail+1)%N==front)
print(“Queue full”)
return
if (ISEMPTY())
front=0
tail=0
else
Array implementation
tail=(tail+1)%N
A[tail]=x
[0] [1] [2] [3] [4]
front
tail
function ENQUEUE(x)
if((tail+1)%N==front)
print(“Queue full”)
return
if (ISEMPTY())
front=0
tail=0
else
Array implementation
tail=(tail+1)%N
A[tail]=x
[0] [1] [2] [3] [4]
front
tail
This way now the tail traverse the array in a circular way
We also need to make the front of the queue
traverse the array in circular way
function DEQUEUE()
if (ISEMPTY())
print(“Queue is empty”)
return
if (front==tail)
front=-1 Array implementation
tail=-1
else
front=(front+1)%N
[0] [1] [2] [3] [4]
front
tail
function PEEK()
if(front==-1)
print(“empty queue”)
return
return A[front]
Array implementation
front
tail
function ISEMPTY()
if(front==-1)
return TRUE
return FALSE
Array implementation
front
tail
function ENQUEUE(x) function DEQUEUE()
if((tail+1)%N==front) if (ISEMPTY())
print(“Queue full”) print(“Queue is empty”)
return return
if (ISEMPTY()) if (front==tail)
front=0 front=-1
tail=0 tail=-1
else else
tail=(tail+1)%N front=(front+1)%N
A[tail]=x
function ISEMPTY()
function PEEK() if(front==-1)
if(front==-1) return TRUE
print(“empty queue”) return FALSE
return
return A[front]
front tail
Summary:
Queue implementation using arrays
Pseudocode
Both front and tail traverse array in a circular
Array implementation
front tail
Queues
implementation lists
Array implementation drawbacks:
• Unused memory locations
front tail
List implementation
NULL NULL
front tail
front tail
List implementation
NULL NULL
front tail
front tail
List implementation
NULL NULL
front tail
NULL
0xE
front tail
List implementation
NULL
0xF
front tail
List implementation
NULL
0xF
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xF tail=newNode
else
…
NULL
0xF
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xF tail=newNode
else
…
NULL
0xF
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xF tail=newNode
else
…
NULL
0xF
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xF tail=newNode
else
…
NULL
0xF
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xF tail=newNode
else
…
NULL NULL
0xF 0xA
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xA tail=newNode
else
tail->next=newNode
0xA NULL
0xF 0xA
front tail
function ENQUEUE(x)
newNode=new Node(x)
List implementation if (front==NULL and tail==NULL)
front=newNode
front 0xF tail 0xA tail=newNode
else
tail->next=newNode
tail=newNode
0xA NULL
0xF 0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front 0xF tail 0xA else
…
0xA NULL
0xF 0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front 0xF tail 0xA else
…
0xA NULL
0xF 0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front 0xF tail 0xA else
front=front->next
0xA NULL
0xF 0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front 0xF tail 0xA else
front=front->next
NULL
0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front NULL tail 0xA else
front=front->next
NULL
0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front NULL tail NULL if(front==tail)
front=NULL
tail=NULL
else
NULL front=front->next
0xA
front tail
function DEQUEUE()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front NULL tail NULL if(front==tail)
front=NULL
tail=NULL
else
front=front->next
front tail
function PEEK()
if(front==NULL and tail==NULL)
List implementation print(“empty queue”)
return
front 0xF tail 0xA else
return front->data
0xA NULL
0xF 0xA
front tail
function ISEMPTY()
if(front==NULL and tail==NULL)
List implementation return TRUE
else
front 0xF tail 0xA return FALSE
0xA NULL
0xF 0xA
function ENQUEUE(x) function DEQUEUE()
newNode=new Node(x) if(front==NULL and tail==NULL)
if (front==NULL and tail==NULL) print(“empty queue”)
front=newNode return
tail=newNode if(front==tail)
else front=NULL
tail->next=newNode tail=NULL
tail=newNode else
front=front->next
function ISEMPTY()
if(front==NULL and tail==NULL) function PEEK()
return TRUE if(front==NULL and tail==NULL)
else print(“empty queue”)
return FALSE return
else
return front->data
Complexity: Theta(1)
front tail
Summary:
Implementation of queue using lists
Pseudocode
Theta(1)