0% found this document useful (0 votes)
36 views20 pages

Stack Implementation with Linked List in Java

The document describes implementations of common data structures using linked lists in Java: 1) A stack is implemented using a linked list with push and pop methods. 2) A queue is implemented using a linked list with insert and delete methods. 3) A deque (double-ended queue) is implemented using a circular array with methods to add/remove from both ends. 4) A deque is also implemented using a doubly linked list. The implementations provide basic methods to add, remove, and view elements in each data structure. Main methods are included to demonstrate functionality.

Uploaded by

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

Stack Implementation with Linked List in Java

The document describes implementations of common data structures using linked lists in Java: 1) A stack is implemented using a linked list with push and pop methods. 2) A queue is implemented using a linked list with insert and delete methods. 3) A deque (double-ended queue) is implemented using a circular array with methods to add/remove from both ends. 4) A deque is also implemented using a doubly linked list. The implementations provide basic methods to add, remove, and view elements in each data structure. Main methods are included to demonstrate functionality.

Uploaded by

Ravi Kiran
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

1.

Stack using
linked list
import [Link].*;
class Stack1
{
Stack1 top,next,prev;
int data;
Stack1()
{
data=0;
next=prev=null;
}
Stack1(int d)
{
data=d;
next=prev=null;
}
void push(int n)
{
Stack1 nn;
nn=new Stack1(n);
if(top==null)
top=nn;
else
{
[Link]=top;
[Link]=nn;
top=nn;
}
}
int pop()
{
int k=[Link];
if([Link]==null)
{
top=null;
return k;
}
else
{
top=[Link];
[Link]=null;
return k;
}
}
boolean isEmpty()
{

if(top==null)
return true;
else
return false;
}

void display()
{
Stack1 ptr;
for(ptr=top;ptr!=null;ptr=[Link])
[Link]([Link]+" ");
}
public static void main(String args[ ])throws Exception
{
int x; int ch;
BufferedReader b=new BufferedReader(new InputStreamReader([Link]));
Stack1 a=new Stack1();
do{
[Link]("enter 1 for pushing");
[Link]("enter 2 for poping");
[Link]("enter 3 for isEmpty");
[Link]("enter 4 for display");
[Link]("Enter 0 for exit");
[Link]("enter ur choice ");
ch=[Link]([Link]()); switch(ch)
{
case 1:[Link]("enter element to insert");
int e=[Link]([Link]());
[Link](e);
break;
case 2:if(![Link]())
{
int p=[Link]();
[Link]("deleted element is "+p);
}
else
{
[Link]("stack is empty");
}
break;
case 3:[Link]([Link]());
break;
case 4:if(![Link]())
{
[Link]();
}
else
{

[Link]("list is empty");
}

while(ch!=0);
}
}

Output:
2. //Queue using Linked list

import [Link].*;
class Qlnk
{
Qlnk front,rear,next;
int data;
Qlnk()
{
data=0;
next=null;
}
Qlnk(int d)
{
data=d;

next=null;
}
Qlnk getFront()
{
return front;
}
Qlnk getRear()
{
return rear;
}
void insertelm(int item)
{
Qlnk nn;
nn=new Qlnk(item);
if(isEmpty())
{
front=rear=nn;
}
else
{
[Link]=nn;
rear=nn;
}
}
int delelm()
{
if(isEmpty())
{
[Link]("deletion failed");
return -1;
}
else
{
int k=[Link];
if(front!=rear)
front=[Link];
else rear=front=null;
return k;
}
}
boolean isEmpty()
{
if(rear==null)
return
true; else
return false;
}
int size()
{
Qlnk ptr;
int cnt=0;
for(ptr=front;ptr!=null;ptr=[Link])
cnt++;
return cnt;
}
void display()
{
Qlnk ptr; if(!
isEmpty())
{
for(ptr=front;ptr!=null;ptr=[Link])
[Link]([Link]+" ");
}
else
[Link]("q is empty");
}
public static void main(String arr[])throws Exception
{
BufferedReader br=new BufferedReader(new
InputStreamReader([Link]));
Qlnk m=new Qlnk();
int ch;
do
{
[Link]("enter 1 for insert");
[Link]("enter 2 for
deletion");
[Link]("enter 3 for
getFront");
[Link]("enter 4 for getRear");
[Link]("enter 5 for size");
[Link]("enter 6 for display");
[Link]("enter 0 for exit");
[Link]("enter ur choice");
ch=[Link]([Link]());
switch(ch)
{
case 1:
[Link]("enter ele to insert");
int item=[Link]([Link]());
[Link](item);
break;

case 2:
int k=[Link]();
[Link]("deleted ele is "+k);
break;

case 3:
[Link]("front index is"+([Link]()).data);
break;

case 4:
[Link]("rear index is"+([Link]()).data);
break;

case 5:
[Link]("size is"+[Link]());
break;

case 6:
[Link]();break;
}

}while(ch!=0);
}
}

Output:
3. implementation of De-queue
(using circular array)
 
// A structure to represent a Deque
class Deque {
    static final int MAX = 100;
    int arr[];
    int front;
    int rear;
    int size;
 
    public Deque(int size)
    {
        arr = new int[MAX];
        front = -1;
        rear = 0;
        [Link] = size;
    }
 
    /*// Operations on Deque:
    void  insertfront(int key);
    void  insertrear(int key);
    void  deletefront();
    void  deleterear();
    bool  isFull();
    bool  isEmpty();
    int  getFront();
    int  getRear();*/
 
    // Checks whether Deque is full or not.
    boolean isFull()
    {
        return ((front == 0 && rear == size - 1)
                || front == rear + 1);
    }
 
    // Checks whether Deque is empty or not.
    boolean isEmpty() { return (front == -1); }
 
    // Inserts an element at front
    void insertfront(int key)
    {
        // check whether Deque if  full or not
        if (isFull()) {
            [Link]("Overflow");
            return;
        }
 
        // If queue is initially empty
        if (front == -1) {
            front = 0;
            rear = 0;
        }
 
        // front is at first position of queue
        else if (front == 0)
            front = size - 1;
 
        else // decrement front end by '1'
            front = front - 1;
 
        // insert current element into Deque
        arr[front] = key;
    }
 
    // function to inset element at rear end
    // of Deque.
    void insertrear(int key)
    {
        if (isFull()) {
            [Link](" Overflow ");
            return;
        }
 
        // If queue is initially empty
        if (front == -1) {
            front = 0;
            rear = 0;
        }
 
        // rear is at last position of queue
        else if (rear == size - 1)
            rear = 0;
 
        // increment rear end by '1'
        else
            rear = rear + 1;
 
        // insert current element into Deque
        arr[rear] = key;
    }
 
    // Deletes element at front end of Deque
    void deletefront()
    {
        // check whether Deque is empty or not
        if (isEmpty()) {
            [Link]("Queue Underflow\n");
            return;
        }
 
        // Deque has only one element
        if (front == rear) {
            front = -1;
            rear = -1;
        }
        else
            // back to initial position
            if (front == size - 1)
            front = 0;
 
        else // increment front by '1' to remove current
            // front value from Deque
            front = front + 1;
    }
 
    // Delete element at rear end of Deque
    void deleterear()
    {
        if (isEmpty()) {
            [Link](" Underflow");
            return;
        }
 
        // Deque has only one element
        if (front == rear) {
            front = -1;
            rear = -1;
        }
        else if (rear == 0)
            rear = size - 1;
        else
            rear = rear - 1;
    }
 
    // Returns front element of Deque
    int getFront()
    {
        // check whether Deque is empty or not
        if (isEmpty()) {
            [Link](" Underflow");
            return -1;
        }
        return arr[front];
    }
 
    // function return rear element of Deque
    int getRear()
    {
        // check whether Deque is empty or not
        if (isEmpty() || rear < 0) {
            [Link](" Underflow\n");
            return -1;
        }
        return arr[rear];
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        Deque dq = new Deque(5);
 
          // Function calls
        [Link](
            "Insert element at rear end  : 5 ");
        [Link](5);
 
        [Link](
            "insert element at rear end : 10 ");
        [Link](10);
 
        [Link]("get rear element : "
                           + [Link]());
 
        [Link]();
        [Link](
            "After delete rear element new rear become : "
            + [Link]());
 
        [Link](
            "inserting element at front end");
        [Link](15);
 
        [Link]("get front element: "
                           + [Link]());
 
        [Link]();
 
        [Link](
            "After delete front element new front become : "
            + +[Link]());
    }
}

Output
Insert element at rear end : 5
insert element at rear end : 10
get rear element 10
After delete rear element new rear become 5
inserting element at front end
get front element 15
After delete front element new front become 5

4. Implementation of Deque using


doubly linked list
import [Link].*;
class GFG
{
 
  // Node of a doubly linked list
  static class Node
  {
    int data;
    Node prev, next;
 
    // Function to get a new node
    static Node getnode(int data)
    {
      Node newNode = new Node();
      [Link] = data;
      [Link] = [Link] = null;
      return newNode;
    }
  };
 
  // A structure to represent a deque
  static class Deque {
    Node front;
    Node rear;
    int Size;
 
    Deque()
    {
      front = rear = null;
      Size = 0;
    }
 
    // Function to check whether deque
    // is empty or not
    boolean isEmpty() { return (front == null); }
 
    // Function to return the number of
    // elements in the deque
    int size() { return Size; }
 
    // Function to insert an element
    // at the front end
    void insertFront(int data)
    {
      Node newNode = [Link](data);
      // If true then new element cannot be added
      // and it is an 'Overflow' condition
      if (newNode == null)
        [Link]("OverFlow\n");
      else {
        // If deque is empty
        if (front == null)
          rear = front = newNode;
 
        // Inserts node at the front end
        else {
          [Link] = front;
          [Link] = newNode;
          front = newNode;
        }
 
        // Increments count of elements by 1
        Size++;
      }
    }
 
    // Function to insert an element
    // at the rear end
    void insertRear(int data)
    {
      Node newNode = [Link](data);
      // If true then new element cannot be added
      // and it is an 'Overflow' condition
      if (newNode == null)
        [Link]("OverFlow\n");
      else {
        // If deque is empty
        if (rear == null)
          front = rear = newNode;
 
        // Inserts node at the rear end
        else {
          [Link] = rear;
          [Link] = newNode;
          rear = newNode;
        }
 
        Size++;
      }
    }
 
    // Function to delete the element
    // from the front end
    void deleteFront()
    {
      // If deque is empty then
      // 'Underflow' condition
      if (isEmpty())
        [Link]("UnderFlow\n");
 
      // Deletes the node from the front end and makes
      // the adjustment in the links
      else {
        Node temp = front;
        front = [Link];
 
        // If only one element was present
        if (front == null)
          rear = null;
        else
          [Link] = null;
 
        // Decrements count of elements by 1
        Size--;
      }
    }
 
    // Function to delete the element
    // from the rear end
    void deleteRear()
    {
      // If deque is empty then
      // 'Underflow' condition
      if (isEmpty())
        [Link]("UnderFlow\n");
 
      // Deletes the node from the rear end and makes
      // the adjustment in the links
      else {
        Node temp = rear;
        rear = [Link];
 
        // If only one element was present
        if (rear == null)
          front = null;
        else
          [Link] = null;
 
        // Decrements count of elements by 1
        Size--;
      }
    }
 
    // Function to return the element
    // at the front end
    int getFront()
    {
      // If deque is empty, then returns
      // garbage value
      if (isEmpty())
        return -1;
      return [Link];
    }
 
    // Function to return the element
    // at the rear end
    int getRear()
    {
 
      // If deque is empty, then returns
      // garbage value
      if (isEmpty())
        return -1;
      return [Link];
    }
 
    // Function to delete all the elements
    // from Deque
    void erase()
    {
      rear = null;
      while (front != null) {
        Node temp = front;
        front = [Link];
      }
      Size = 0;
    }
  }
 
  // Driver program to test above
  public static void main(String[] args)
  {
    Deque dq = new Deque();
    [Link](
      "Insert element '5' at rear end\n");
    [Link](5);
 
    [Link](
      "Insert element '10' at rear end\n");
    [Link](10);
    [Link]("Rear end element: " + [Link]()
                     + "\n");
    [Link]();
    [Link](
      "After deleting rear element new rear"
      + " is: " + [Link]() + "\n");
    [Link](
      "Inserting element '15' at front end \n");
    [Link](15);
    [Link](
      "Front end element: " + [Link]() + "\n");
 
    [Link]("Number of elements in Deque: "
                     + [Link]() + "\n");
    [Link]();
    [Link]("After deleting front element new "
                     + "front is: " + [Link]()
                     + "\n");
  }
}
Output
Insert element '5' at rear end
Insert element '10' at rear end
Rear end element: 10
After deleting rear element new rear is: 5
Inserting element '15' at front end
Front end element: 15
Number of elements in Deque: 2
After deleting front element new front is: 5

5. Program to implement Priority Queue


// using Arrays

import [Link].*;
 
// Structure for the elements in the
// priority queue
class item {
  public int value;
  public int priority;
};
 
class GFG {
 
  // Store the element of a priority queue
  static item[] pr = new item[100000];
 
  // Pointer to the last index
  static int size = -1;
  // Function to insert a new element
  // into priority queue
  static void enqueue(int value, int priority)
  {
    // Increase the size
    size++;
 
    // Insert the element
    pr[size] = new item();
    pr[size].value = value;
    pr[size].priority = priority;
  }
 
  // Function to check the top element
  static int peek()
  {
    int highestPriority = Integer.MIN_VALUE;
    int ind = -1;
 
    // Check for the element with
    // highest priority
    for (int i = 0; i <= size; i++) {
 
      // If priority is same choose
      // the element with the
      // highest value
      if (highestPriority == pr[i].priority
          && ind > -1
          && pr[ind].value < pr[i].value) {
        highestPriority = pr[i].priority;
        ind = i;
      }
      else if (highestPriority < pr[i].priority) {
        highestPriority = pr[i].priority;
        ind = i;
      }
    }
 
    // Return position of the element
    return ind;
  }
 
  // Function to remove the element with
  // the highest priority
  static void dequeue()
  {
    // Find the position of the element
    // with highest priority
    int ind = peek();
 
    // Shift the element one index before
    // from the position of the element
    // with highest priority is found
    for (int i = ind; i < size; i++) {
      pr[i] = pr[i + 1];
    }
 
    // Decrease the size of the
    // priority queue by one
    size--;
  }
 
  public static void main(String[] args)
  {
    // Function Call to insert elements
    // as per the priority
    enqueue(10, 2);
    enqueue(14, 4);
    enqueue(16, 4);
    enqueue(12, 3);
 
    // Stores the top element
    // at the moment
    int ind = peek();
 
    [Link](pr[ind].value);
 
    // Dequeue the top element
    dequeue();
 
    // Check the top element
    ind = peek();
    [Link](pr[ind].value);
 
    // Dequeue the top element
    dequeue();
 
    // Check the top element
    ind = peek();
    [Link](pr[ind].value);
  }
}

Output
16
14
12

Common questions

Powered by AI

Stacks, queues, and deques have different structural properties. In the stack implementation , elements are added and removed from the same end, called the 'top,' following Last-In-First-Out (LIFO) order. In contrast, the queue implementation follows First-In-First-Out (FIFO) order, where elements are added at the 'rear' and removed from the 'front.' Deques, as implemented in Source 2 and Source 3, can insert and remove elements from both ends, providing greater flexibility, but with the additional complexity of checking for overflow conditions due to their circular or doubly linked list structures.

A priority queue differs from a standard queue in that each element is associated with a priority. The dequeue operation in a priority queue removes the element with the highest priority rather than the oldest element as in a standard queue. The array-based priority queue implementation we see here maintains elements by priority and uses additional logic to selectively dequeue the highest-priority element, whereas a standard queue implementation just follows a FIFO order without considering priority.

In a deque implementation using a dynamic-size data structure like a linked list , insertion and deletion operations generally occur in constant time, O(1), because elements can be added or removed from the front or rear without needing to shift other elements. This is in contrast to an array-based implementation, where resizing to accommodate more elements can introduce additional complexity, making certain operations take longer (i.e., O(n) due to copying elements during resizing). Therefore, linked list implementations enable more efficient insertions and deletions as the deque size dynamically changes.

The key advantages of using a linked list over an array for stack implementation, as shown in Source 1, include dynamic memory usage, since linked lists do not require pre-allocation of memory. This allows the stack to grow and shrink in size as elements are pushed and popped, respectively, without encountering overflow until system memory is exhausted. Moreover, linked lists eliminate the need for resizing, avoiding the performance hit associated with copying elements during an array resize. Additionally, each push and pop operation has a time complexity of O(1) in a linked list, compared to the possible need to shift elements in array-based stacks.

A queue implemented with a linked list, as described in Source 1, can handle infinite item insertions as it dynamically allocates memory for new nodes, avoiding the fixed size limitation of arrays. This ensures efficient use of memory as only the required amount of memory is allocated for active nodes. As the list grows with each insertion (additions are linked through the 'rear') and shrinks with each deletion ('front' node is removed), the use of pointers ensures that only the necessary amount of memory for the existing elements is used, thus adapting dynamically to the queue's size.

In the circular array deque implementation , underflow is managed by checking if the deque is empty using isEmpty(). Operations like deletefront() and deleterear() return an error message when the deque is empty. Overflow is controlled using isFull(), which checks if the array is full using conditions such as (front == 0 && rear == size - 1) || front == rear + 1. If an operation attempts to insert into a full deque, an overflow error message is displayed, preventing additional insertions.

Using a doubly linked list for deque implementations, as seen in Source 3, allows constant-time insertions and deletions from both ends of the deque. Each node has pointers to both the next and previous nodes, facilitating operations that can traverse in both directions. This contrasts with a singly linked list, which only allows traversal in one direction, requiring linear time complexity to perform operations at the opposite end. The additional backward link in a doubly linked list decreases the need for reversing lists or traversing the entire list to perform deletions or insertions at the rear end.

When a circular array is used for implementing a deque and its size limit is frequently reached, it can lead to performance inefficiencies such as frequent handling of overflow conditions, which interrupts normal operations. Persistent size limits can necessitate resizing operations or data structure reorganization, which are costly in terms of performance, as they involve moving multiple data elements. Frequent reaching of size limits might impel the need for a data structure change, such as moving to a linked-list-based design that inherently does not have size constraints, allowing for indefinite growth.

A circular array may be preferred over a linked list for implementing a deque because it allows for faster access and is generally simpler to manage in terms of memory usage. This can be beneficial when the maximum size of the deque is known in advance and operations need to be performed quickly, as resizing is not required. Furthermore, circular arrays avoid the overhead of managing multiple pointers, as seen in a linked list implementation. However, they are constrained by a fixed size, which can lead to overflow if the deque becomes full.

A doubly linked list would be more appropriate than an array for implementing a deque in scenarios where flexible size adjustments are required and operations at both ends are performed frequently. This includes applications needing fast insertions and deletions without being constrained by a predefined capacity, which arrays impose. Additionally, when the list's size changes dynamically and significantly, such as in applications with volatile data where the deque size exhibits large variations, the constant-time complexity for inserting and removing elements at both ends in a doubly linked list outweighs the higher per-node memory usage.

You might also like