0% found this document useful (0 votes)
17 views8 pages

Implementing Stacks and Queues in Java

The document discusses stacks and queues implemented using arrays. It defines stacks and queues as abstract data types and describes their common operations like push, pop, peek, isEmpty etc. It then provides an implementation of stacks and queues using arrays in Java with methods like push(), pop() etc. It includes code examples to demonstrate adding/removing elements from both stacks and queues and printing the results.

Uploaded by

Aimen Khalid
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)
17 views8 pages

Implementing Stacks and Queues in Java

The document discusses stacks and queues implemented using arrays. It defines stacks and queues as abstract data types and describes their common operations like push, pop, peek, isEmpty etc. It then provides an implementation of stacks and queues using arrays in Java with methods like push(), pop() etc. It includes code examples to demonstrate adding/removing elements from both stacks and queues and printing the results.

Uploaded by

Aimen Khalid
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

ARRAY STACKS AND

QUEUES
Lab-09

Data structures and Algorithms-Lab-Lab [COSC-2201] 76


Stacks and Queues

1. Write java program to implement the following using an Array.


a. Stack ADT
b. Queue ADT

Stack
A stack is a conceptual structure consisting of a set of homogeneous elements and is based on the
principle of last in first out (LIFO). It is a commonly used abstract data type with two major
operations, namely push and pop.

Figure 10: Stack Metaphor Figure 11: Stack Push and Pop illustration

Stack ADT
Stack as an Abstract Data type supports the following operations:
push(Obj): add object at the top of the stack.
Input: Object ; Output: None
Obj pop( ): Delete an item from the top of the stack and returns object obj; an error
occurs if the stack is empty.
Input: None; Output: Object.
Obj peek( ): Returns the top object obj on the stack , without removing it; an error
occurs if the stack is empty.
Input: None; Output: Object.
boolean isEmpty( ): Returns a boolean indicating if the stack is empty.
Input: None; Output: boolean (true or false).
boolean isFull( ): Returns a boolean indicating if the stack is full.
Input: None; Output: boolean (true or false).

Data structures and Algorithms-Lab-Lab [COSC-2201] 77


int size( ): Returns the number of items on the stack.
Input: None; Output: integer.

The push, pop, peek, empty, and size operations are translated directly into specifications for methods
named push(), pop(), peek(), isEmpty(), isFull(), and size() respectively. These are conventional
names for stack operations. Each method is defined by specifying its return value and any changes
that it makes to the object.

public class StackUsingArray {

private int arr[];


private int size;
private int index = 0;

public StackUsingArray(int size) {


[Link] = size;
arr = new int[size];
}

public void push(int element) {

if (isFull()) {
[Link]("Stack is full");
}

arr[index] = element;
index++;
}

public int pop() {

if (isEmpty()) {
[Link]("Stack is Empty");
}
return arr[--index];

Data structures and Algorithms-Lab-Lab [COSC-2201] 78


public boolean isEmpty() {
if (index == 0) {
return true;
}
return false;
}

public boolean isFull() {


if (index == size) {
return true;
}
return false;
}

public int size() {


return index;
}

public static void main(String[] args) {

StackUsingArray stack = new StackUsingArray(5);


[Link](5);
[Link](4);

[Link](3);
[Link](2);
[Link](1);

[Link]("1. Size of stack after push operations: " +


[Link]());

[Link]("2. Pop elements from stack : ");


while (![Link]()) {
[Link](" %d", [Link]());
}

[Link]("\n3. Size of stack after pop operations : " +


Queue
[Link]());

A Queue is a linear structure which follows a particular order in which the operations are performed.
}
The order is First In First Out (FIFO). A good example of a queue is any queue of consumers for a
resource where the consumer that came first is served first. The difference between stacks and queues
is in removing.

Data structures and Algorithms-Lab-Lab [COSC-2201] 79


Figure 12: Queue as linear Data structure
Figure 13: Queue as Circular Data Structure

Queue ADT
The elements in a queue are of generic type Object. The queue elements are linearly ordered
from the front to the rear. Elements are inserted at the rear of the queue (enqueued) and are
removed from the front of the queue (dequeued).

A Queue is an Abstract Data Type (ADT) that supports the following methods:
insert(obj): Adds object obj at the rear of a queue.
Input: Object; Output: None.
obj remove(): Deletes an item from the front of a queue and returns object obj; an
error occurs if the queue is empty.
Input: None; Output: Object.
obj peek(): Returns the object obj at the front of a queue , without removing it; an
error occurs if the queue is empty.
Input: None; Output: Object.
boolean isEmpty(): Returns a boolean indicating if the queue is empty.
Input: None; Output: boolean (true or false).
boolean isFull(): Returns a boolean indicating if the queue is Full.
Input: None; Output: boolean (true or false).
int size(): Returns the number of items in the queue.
Input: None; Output: integer.

Type Object may be any type that can be stored in the queue. The actual type of the object
will be provided by the user. The ADT is translated into a Java interface in Program 17(d).

public interface Queue {


public void insert(Object ob);
public Object remove();
public Object peek();
public boolean isEmpty();
public boolean isFull();
public int size();
}

Data structures and Algorithms-Lab-Lab [COSC-2201] 80


Note the similarities between these specifications and that of the stack interface. The only
real difference, between the names of the operations, is that the queue adds new elements at
the opposite end from which they are accessed, while the stack adds them at the same end.

Queue Implementation
The ArrayQueue implementation of queue interface is done by taking an array, que[n] and
treating it as if it were circular. The elements are inserted by increasing rear to the next free
position. When rear = n-1, the next element is entered at que[0] in case that spot is free. That
is, the element que[n-1] follows que[0]. Program 17(e) implements the ArrayQueue class,
and Program 17(f) tests this class.

class ArrayQueue implements Queue {


private int maxSize; // maximum queue size
private Object[] que; // que is an array
private int front;
private int rear;
private int count; // count of items in queue (queue size)
public ArrayQueue(int s) // constructor
{
maxSize = s;
que = new Object[maxSize];
front = rear = -1;
count = 0;
}
public void insert(Object item) // add item at rear of queue
{
if (count == maxSize) {
[Link]("Queue is Full");
return;
}
if (rear == maxSize - 1 || rear == -1) {
que[0] = item;
rear = 0;
if (front == -1) front = 0;
} else que[++rear] = item;
count++; // update queue size
}
public Object remove() // delete item from front of queue
{
if (isEmpty()) {
[Link]("Queue is Empty");
return 0;
}
Object tmp = que[front]; // save item to be deleted
que[front] = null; // make deleted item’s cell empty
if (front == rear)
rear = front = -1;
else if (front == maxSize - 1) front = 0;

Data structures and Algorithms-Lab-Lab [COSC-2201] 81


else front++;
count--; // less one item from the queue size
return tmp;
}
public Object peek() // peek at front of the queue
{
return que[front];
}
public boolean isEmpty() // true if the queue is empty
{
return (count == 0);
}
public int size() // current number of items in the queue
{
return count;
}
public void displayAll() {
[Link]("Queue: ");
for (int i = 0; i < maxSize; i++)
[Link](que[i] + " ");
[Link]();
}
}

class QueueDemo {
public static void main(String[] args) {
/* queue holds a max of 5 items */
ArrayQueue q = new ArrayQueue(5);
Object item;
[Link]('A');
[Link]('B');
[Link]('C');
[Link]();
item = [Link](); // delete item
[Link](item + " is deleted");
item = [Link]();
[Link](item + " is deleted");
[Link]();
[Link]('D'); // insert 3 more items
[Link]('E');
[Link]('F');
[Link]();
item = [Link]();
[Link](item + " is deleted");
[Link]();
[Link]("peek(): " + [Link]());
[Link]('G');
[Link]();
[Link]("Queue size: " + [Link]());
}}

Data structures and Algorithms-Lab-Lab [COSC-2201] 82


Output of this program is as follows:
Queue: A B C null null
A is deleted
B is deleted
Queue: null null C null null
Queue: F null C D E
C is deleted
Queue: F null null D E
peek(): D
Queue: F G null D E
Queue size: 4

Data structures and Algorithms-Lab-Lab [COSC-2201] 83

Common questions

Powered by AI

Stacks operate on a LIFO (Last In, First Out) principle where the last element added is the first to be removed. This means operations such as push (to add an element) and pop (to remove an element) occur at the same end, which is referred to as the top . Conversely, queues operate on a FIFO (First In, First Out) principle, meaning the first element added is the first to be removed. In a queue, the insert operation (enqueue) occurs at the rear end, while the removal operation (dequeue) happens at the front end . These differences in operation order mean that stacks are useful for reversing order or backtracking tasks, whereas queues are suited for tasks involving processing or servicing resources in the order they were received, such as in a scheduling or buffering scenario .

In an array-based implementation of a stack, elements are added and accessed at the same end, which is typically the top of the stack, making it simple and direct . In contrast, an array-based queue treats the array as if it were circular, with elements enqueued at the rear and dequeued at the front. As the rear reaches the end of the array, it wraps around to the beginning if space is available, ensuring efficient use of space . This circular behavior requires additional logic to manage front and rear pointers, contributing to its complexity but enhancing effective space utilization .

The "isFull" method in both stack and queue implementations using arrays checks whether the data structure has reached its maximum capacity, which is essential for preventing overflow errors during push or insert operations, respectively. For stacks, "isFull" returns true when the index is equivalent to the array size, indicating no more elements can be added without exceeding the capacity . For queues, "isFull" checks if the count of elements is equal to the maximum size, ensuring the queue can no longer accept new elements unless some are dequeued first . This method plays a critical role in managing memory usage efficiently and controlling subsequent operations by signaling when capacity limits are approached, prompting either error handling or preventive measures to manage structure growth .

Both stacks and queues typically have O(1) time complexity for their primary operations - push, pop, peek in stacks; enqueue (insert), dequeue (remove), and peek in queues. This constant time efficiency is due to direct element access positions - the top for stacks and front/rear for queues. However, factors such as array resizing or using linked lists can affect this efficiency. In stacks, efficiency may degrade if resizing is needed upon reaching capacity, incurring additional O(n) cost. In queues, while operations are O(1) under normal circumstances, issues with non-circular implementations may lead to inefficiencies due to shifting elements, which a circular array effectively mitigates by allowing placements at both ends without shifts, maintaining O(1) performance .

In a stack, an error can occur during a pop or peek operation if the stack is empty, commonly referred to as an underflow condition. This is typically handled by checking if the stack is empty before attempting these operations, potentially throwing an error message or exception . Similarly, a push operation may result in an overflow error if the stack is full. Implementations often check for fullness before pushing, returning an error message if necessary . In queues, underflow can occur when a remove or peek operation is performed on an empty queue, while overflow occurs when attempting to insert into a full queue. These conditions are handled by checking the isEmpty or isFull status respectively before executing the operations, thereby preventing illegal accesses and maintaining data integrity .

The "peek" method allows for viewing the element at the front of the queue or the top of the stack without removing it, serving a diagnostic or preview function . In a stack, peek provides insight into the most recently added item, allowing decisions based on current stack content without altering its structure, which is crucial for LIFO operations. In queues, peeking at the front element helps in understanding what will be dequeued next, crucial for FIFO processing tasks. This method helps in managing data structures without performing any modifying operations, preserving the integrity and content order while allowing inspection .

Implementing a stack using an array involves defining methods for the core stack operations: push, pop, peek, isEmpty, isFull, and size. The push method adds an element to the top of the stack, increasing the index for each insertion, while pop removes the top element, decreasing the index, ensuring LIFO functionality . The peek method allows users to view the top element without removing it, providing insight into the stack’s content without modifying it . The isEmpty and isFull methods check whether the stack is currently empty or at maximum capacity, preventing illegal operations . Each of these methods must update the stack’s index and/or size appropriately to maintain correct functionality. Finally, the size method returns the current number of elements in the stack, helping manage capacity and usage .

The "displayAll" method enhances the usability and debugging process by providing a visual representation of the queue's current state, including both the filled and unfilled slots. This method iterates through the que array, outputting the content of each position, which is valuable for understanding how elements are distributed, especially given the circular nature of the array implementation used in queues . The clarity thus provided helps in quickly identifying issues such as unused spaces due to wrapping errors or imbalance in front and rear index adjustments, aiding developers in verifying logic correctness and ensuring consistent queue behavior, ultimately simplifying the maintenance and debugging tasks .

A circular array enhances space efficiency in a queue by allowing the rear of the queue to wrap around to the front of the array once it reaches the end, provided there is free space. This prevents having unused slots at the beginning of the array when elements are removed, which commonly occurs in a non-circular or linear array . Thus, the circular implementation eliminates the need to shift elements after every dequeue operation, maintaining constant time complexity for both enqueue and dequeue operations. By treating the array as circular, the implementation ensures all available space is efficiently utilized, reducing the need for resizing or dealing with a full array unless it truly has reached maximum storage capacity .

Implementing a queue with a fixed-size array can lead to inefficiencies related to overflow when the queue becomes full, and underutilization of space when elements are removed but the array slots remain inaccessible due to linear constraints . Another issue is that fixed size limits flexibility in handling dynamic workloads. These drawbacks can be mitigated by adopting a circular array approach, which allows wrapping around the array's end to the beginning, optimizing usage of available space . Alternatively, using a dynamic array or linked list implementation can adjust the capacity on-the-fly, although these might sacrifice O(1) time complexity or introduce additional overhead .

You might also like