Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

DSA with Java/Unit- 3

Unit 3: Stack and Queue


Stacks
 A stack is a linear data structure that can be accessed only at one of its ends for storing and
retrieving data.
 Such a stack resembles a stack of trays in a cafeteria: New trays are put on the top of the
stack and taken off the top. The last tray put on the stack is the first tray removed from the
stack (LIFO structure). A tray can be taken only if there are trays on the stack, and a tray
can be added to the stack only if there is enough room; that is, if the stack is not too
high.(operations and status)
 The stack is called an LIFO structure: last in/first out.
 The stack is defined in terms of operations that change its status and operations that check
this status. The operations are as follows:
 clear( ) — Clear the stack.
 isEmpty( ) — Check to see if the stack is empty.
 push(el) — Put the element el on the top of the stack.
 pop( ) — Take the topmost element from the stack.
 topElement( ) — Return the topmost element in the stack without
removing it.

Figure 1:A series of operations executed on a stack.

1
Collected by Bipin Timalsina
DSA with Java/Unit- 3

 Special names are given to the two changes that can be made to a stack. When an element
is inserted in a stack, the concept is called push, and when an element is removed from the
stack, the concept is called pop. Trying to pop out an empty stack is called underflow and
trying to push an element in a full stack is called overflow.
 Generally, the stack is very useful in situations when data have to be stored and then
retrieved in reverse order.
 Some applications :
 One application of the stack is in matching delimiters (Symbols) in a program. This
is an important example because delimiter matching is part of any compiler: No
program is considered correct if the delimiters are mismatched.
 Another application is in adding very large integers. The largest magnitude of
integers is limited, so we are not able to add
18,274,364,583,929,273,748,459,595,684,373 and 8,129,498,165,026,350,236,
because integer variables cannot hold such large values, let alone their sum. The
problem can be solved if we treat these numbers as strings of numerals, store the
numbers corresponding to these numerals on two stacks, and then perform addition
by popping numbers from the stacks.
 Another important example is a stack used by the Java Virtual Machine (JVM).

(Please go through text book for detail explanation for above applications)

Implementation of Stack
There are many ways of implementing stack; below are the commonly used methods:
 Simple array based implementation
• Dynamic array based implementation
• Linked lists implementation

2
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Java Class to implement Stack using Array


class Stack {
static final int MAX = 2;
int top;
//assigning MAX size of the stack
int stkArr[] = new int[MAX];

Stack() {
top = -1;
}
// create a method to check whether
// the stack is empty or not
void isEmpty() {
if(top == -1) {
System.out.println("Stack is empty.");
} else {
System.out.println("Stack is not empty.");
}
}

//create a method to return size of the stack


int size() {
return top+1;
}

//create a method to add new element


void push(int x){
if(top == (MAX - 1)){
System.out.println("Overflow! the stack is full");
} else {
stkArr[++top] = x;
System.out.println(x + " is pushed into the stack");
}
}
//create a method to delete top element
void pop(){
if(top < 0){
System.out.println("Underflow! the stack is empty");
} else {
int x = stkArr[top--];
System.out.println(x + " is deleted from the stack");
}
}

3
Collected by Bipin Timalsina
DSA with Java/Unit- 3

//create a method to get top element


int topElement() {
if(top < 0) {
System.out.println("Underflow! the stack is empty");
return 0;
} else {
return stkArr[top];
}
}
}
Java Class to implement Stack using Dynamic Array (ArrayList )
class MStack {
private ArrayList<Object> arrList = new ArrayList<Object>();
boolean sizeIsGiven = false;
int givenSize;
public ALStack() {
}
public ALStack(int n) {
arrList.ensureCapacity(n);
sizeIsGiven=true;
givenSize=n;
}
public void clear() {
arrList.clear();;
System.out.println("Stack is cleared");

}
public boolean isEmpty() {
return arrList.isEmpty();
}
public Object topElement() {
if (isEmpty())
System.out.println("Underflow!Stack is empty");
return arrList.get(arrList.size()-1);
}
public void pop() {
if (isEmpty())
System.out.println("Underflow!Stack is empty");
int lastElementPosition =arrList.size()-1;
Object lastElement = arrList.get(lastElementPosition);
arrList.remove(lastElementPosition);
System.out.println(lastElement+ " is popped from the stack");
}
public void push(Object el) {
if(sizeIsGiven && arrList.size()>=givenSize) {

4
Collected by Bipin Timalsina
DSA with Java/Unit- 3

System.out.println("Overflow!Stack is full");
}
else {
arrList.add(el);
System.out.println(el + " is pushed to the stack"+arrList.size());
}
}
}
Java Class to implement Stack using Linked List (LinkedList )
import java.util.LinkedList;
class LStack {
private LinkedList<Object> list = new LinkedList<Object>();
public LStack() {
}
public void clear() {
list.clear();
System.out.println("Stack is cleared");

}
public boolean isEmpty() {
return list.isEmpty();
}
public Object topElement() {
if (isEmpty())
System.out.println("Underflow! the stack is empty");
return list.getLast();
}
public void pop() {
if (isEmpty())
System.out.println("Underflow! the stack is empty ");
Object lastElement= list.getLast();
list.removeLast();
System.out.println(lastElement+ " is popped from stack");
}
public void push(Object el) {
list.addLast(el);
System.out.println(el + " is pushed to the stack");
}

5
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Figure 2: A series of operations executed on an abstract stack (a) and the stack implemented with a dynamic array (b) and
with a linked list (c).

Case Study
Explore the java.util.Stack class and list the important methods. Write a Java Program to show
stack operations using this class.

Queues
 A queue is simply a waiting line that grows by adding elements to its end and
shrinks by taking elements from its front.
 Unlike a stack, a queue is a structure in which both ends are used: one for adding
new elements and one for removing them.
 A queue is a data structure in which insertions are done at one end (rear) and
deletions are done at other end (front).
 Therefore, the last element has to wait until all elements preceding it on the queue
are removed.
 A queue is an FIFO structure: first in/first out. (The first element to be inserted is
the first one to be deleted)

6
Collected by Bipin Timalsina
DSA with Java/Unit- 3

 Queue operations are similar to stack operations. The following operations are
needed to properly manage a queue:
■ clear()—Clear the queue.
■ isEmpty()—Check to see if the queue is empty.
■ enqueue(el)—Put the element el at the end of the queue.
■ dequeue()—Remove the first element from the queue.
■ firstElement()—Return the first element in the queue without removing it

Figure 3: A Series of operations executed in a queue

 Similar to Stacks, special names are given to the two changes that can be made to a queue.
When an element is inserted in a queue, the concept is called enqueue, and when an
element is removed from the queue, the concept is called dequeue. Dequeueing an empty
queue is called underflow and enqueuing an element in a full queue is called overflow
 Some applications :
 Operating systems schedule jobs (with equal priority) in the order of arrival
(e.g., a print queue).
 Simulation of real-world queues such as lines at a ticket counter, or any other
first come first-served scenario requires a queue.

7
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Implementation of Queue
There are many ways (similar to Stacks) of implementing queue operations and some of the
commonly used methods are listed below.
• Circular array based implementation (Simple and Dynamic Array)
• Linked list implementation
Why Circular Arrays?
We can use simple arrays for implementing queues as we have done for stacks. We know that, in
queues, the insertions are performed at one end and deletions are performed at the other end.
Elements are added to the end of the queue, but they may be removed from its beginning, thereby
releasing array cells. This is simply the memory wastage. So, simple array implementation for
queue is not efficient.
To solve this problem we assume the arrays as circular arrays. That means, we treat the last element
and the first array elements as contiguous. With this representation, if there are any free slots at
the beginning, the rear pointer can easily go to its next free slot.
[Generally, a front is used to indicate the start element and rear is used to indicate the end element
in the queue.]

Figure 4: Problem in Normal Array Implementation of Queue

8
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Figure 5: Circular Array Implementation of Queue

 The queue is full if the first element immediately precedes in the counterclockwise
direction the last element.
 However, because a circular array is implemented with a “normal” array, the queue is full
if either the first element is in the first cell and the last element is in the last cell (Figure
6a) or if the first element is right after the last (Figure 6b).
 Similarly, enqueue() and dequeue() have to consider the possibility of wrapping around
the array when adding or removing elements. For example, enqueue() can be viewed as
operating on a circular array (Figure 6c), but in reality, it is operating on a one-dimensional
array.
 Therefore, if the last element is in the last cell and if any cells are available at the beginning
of the array, a new element is placed there (Figure 6d).
 If the last element is in any other position, then the new element is put after the last, space
permitting (Figure 6e).
 These two situations must be distinguished when implementing a queue viewed as a
circular array (Figure 6f).

9
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Figure 6: (a– b) Two possible configurations in an array implementation of a queue when the
queue is full. (c) The same queue viewed as a circular array. (f) Enqueuing number 6 to a queue
storing 2, 4, and 8. (d– e) The same queue seen as a one-dimensional array with the last element
(d) at the end of the array and (e) in the middle.

10
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Simple Circular Array Implementation of Queue


public class ArrayQueue {
private int first,last,size;
private Object[] storage;
public ArrayQueue() {
this(100);
}
public ArrayQueue(int n) {
size = n;
storage = new Object[size];
first = last = -1;
}
public boolean isFull() {
if(first == 0 && last == size-1 || first == last + 1)
return true;
else
return false;
}
public boolean isEmpty() {
if(first == -1)
return true;
else
return false;
}
public void enqueue(Object el) {
if(isFull()){
System.out.println("Overflow! the queue is full!");
}
else {
if (last == size-1 || last == -1) {
storage[0] = el;
last = 0;
if (first == -1)
first = 0;
}
else {
storage[++last] = el;
}
System.out.println(el+ " is added to the queue");
}
}
public void dequeue() {
if(isEmpty()) {
System.out.println("Underflow!the queue is empty");
11
Collected by Bipin Timalsina
DSA with Java/Unit- 3

}
else {
Object temp = storage[first];
if (first == last)
last = first = -1;
else if (first == size-1)
first = 0;
else
first++;
System.out.println(temp +" is removed from the queue");
}
}
public void printAll() {
if(isEmpty()) {
System.out.println("The queue is empty");
}
else {
for (int i = first; i < size; i++)
System.out.print(storage[i] + " ");
}
}
}

Linked List Implementation


Another way of implementing queues is by using Linked lists. Enqueue operation is implemented
by inserting an element at the end of the list. Dequeue operation is implemented by deleting an
element from the beginning of the list.
import java.util.LinkedList;
class Queue {
private LinkedList <Object>list = new LinkedList<Object>();
public Queue() {
}
public void clear() {
list.clear();
}
public boolean isEmpty() {
return list.isEmpty();
}
public Object firstElement() {
return list.getFirst();
}
public void dequeue() {

12
Collected by Bipin Timalsina
DSA with Java/Unit- 3

if(!isEmpty()) {
Object fe = list.removeFirst();
System.out.println(fe + " is removed from the queue");
}
else {
System.out.println("Underflow! the queue is empty");
}

}
public void enqueue(Object el) {
list.addLast(el);
System.out.println(el + " is added to the queue");
}
}

Figure 7: A series of operations executed on an abstract queue (a) and the queue implemented
with an array (b) and with a linked list (c).

13
Collected by Bipin Timalsina
DSA with Java/Unit- 3

Priority Queues
 In many situations, simple queues are inadequate, as when first in/first out scheduling has
to be overruled using some priority criteria.(In a queue of people, handicapped and old
aged persons are given priority over others. Right? )
 In a sequence of processes, process P2 may need to be executed before process P1 for the
proper functioning of a system, even though P1 was put on the queue of waiting processes
before P2. In situations like these, a modified queue, or priority queue, is needed.
 In priority queues, elements are dequeued according to their priority and their current queue
position.
 The problem with a priority queue is in finding an efficient implementation that allows
relatively fast enqueuing and dequeuing. Because elements may arrive randomly to the
queue, there is no guarantee that the front elements will be the most likely to be dequeued
and that the elements put at the end will be the last candidates for dequeuing.
 The situation is complicated because a wide spectrum of possible priority criteria can be
used in different cases such as frequency of use, birthday, salary, position, status, and
others.
Case Study: Exiting a Maze
Please go through the text book, rewrite the problem and solution strategy. Also write a
Java program to solve the problem.

Assignment
What do you mean by ADT? Give some examples.

14
Collected by Bipin Timalsina

You might also like