Category: Stack & Queue

  • Deque Data Structure

    Deque is a hybrid data structure that combines the features of a stack and a queue. It allows us to insert and delete elements from both ends of the queue. The name Deque is an abbreviation of Double-Ended Queue.

    Imagine an event where you have two gates to enter and exit a place. People are entering from the front gate and some are entering from the side gate. Now, when people are leaving, they are leaving from the front gate and some sneak from the side gate. Now, we need to manage flow of people from both ends. This is where Deque comes into play.

    Operations on Deque

    Following are the major operations on Deque −

    • push_front(x): Insert element x at the front of the deque.
    • push_back(x): Insert element x at the back of the deque.
    • pop_front(): Remove the element from the front of the deque.
    • pop_back(): Remove the element from the back of the deque.
    • peek_front(): Get the element from the front of the deque.
    • peek_back(): Get the element from the back of the deque.
    • size(): Get the number of elements in the deque.
    • isEmpty(): Check if the deque is empty.

    Implementation of Deque

    Let’s understand how we can implement deque using array. For this, we need to maintain two pointers, front and rear, to keep track of the front and back of the deque. We also need to define the size of the deque.

    The push_front(x) Operation on Deque

    When we insert an element at the front of the deque, we need to shift all the elements to the right by one position. We will increment the front pointer by one and insert the element at the front of the deque.

    Algorithm for push_front(x)

    Following are the steps to insert an element at the front of the deque −

    1. Check if the deque is full. If it is full, return an error message.
    2. Increment the front pointer by one.
    3. Insert the element at the front position.
    4. Increment the size of the deque.
    

    implementation

    Following is the implementation of push_front(x) operation on deque.

    CC++JavaPython

    #include <stdio.h>#include <stdlib.h>#define SIZE 5int deque[SIZE];int front =-1, rear =-1;// Check if the deque is fullintisFull(){return(front ==0&& rear == SIZE -1)||(front == rear +1);}// Check if the deque is emptyintisEmpty(){return front ==-1;}// Insert element at the frontvoidpush_front(int element){if(isFull()){printf("Deque is full\n");return;}if(isEmpty()){// First element being inserted
          front = rear =0;}else{// Circularly move front pointer
          front =(front -1+ SIZE)% SIZE;}
    
       deque[front]= element;printf("Inserted -> %d\n", element);}// Display the dequevoiddisplay(){if(isEmpty()){printf("Empty Deque\n");return;}int i = front;printf("Elements -> ");while(1){printf("%d ", deque[i]);if(i == rear)break;// Stop at the last element
          i =(i +1)% SIZE;// Circular increment}printf("\n");}intmain(){push_front(1);push_front(2);push_front(3);push_front(4);push_front(5);display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Inserted -> 4
    Inserted -> 5
    Elements -> 5 4 3 2 1   
    

    push_back(x) Operation

    This operation is used for inserting an element to the back of the deque. When we insert an element at the back of the deque, we need to increment the rear pointer by one and insert the element at the back of the deque.

    Algorithm for push_back(x)

    Following are the steps to insert an element at the back of the deque −

    1. Check if the deque is full.
    2. Increment the rear pointer by one.
    3. Insert the element at the rear position.
    4. Increment the size of the deque.
    

    Implementation

    Following is the implementation of push_back(x) operation on deque.

    CC++JavaPython

    //C Program#include <stdio.h>#include <stdlib.h>#define SIZE 5int deque[SIZE];int front =-1, rear =-1;// Check if the deque is fullintisFull(){return((front ==0&& rear == SIZE -1)||(front == rear +1));}// Check if the deque is emptyintisEmpty(){return(front ==-1);}// Insert element at the backvoidpush_back(int element){if(isFull()){printf("Deque is full\n");}else{if(front ==-1){// If deque is initially empty
             front = rear =0;}elseif(rear == SIZE -1){// Wrap around to the front
             rear =0;}else{
             rear++;}
          deque[rear]= element;printf("Inserted -> %d\n", element);}}// Display the dequevoiddisplay(){if(isEmpty()){printf("Empty Deque\n");}else{printf("Elements -> ");int i = front;while(1){printf("%d ", deque[i]);if(i == rear)break;// Stop when the rear is reached
             i =(i +1)% SIZE;// Circular increment}printf("\n");}}// Main functionintmain(){push_back(1);push_back(2);push_back(3);push_back(4);push_back(5);display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Inserted -> 4
    Inserted -> 5
    Elements -> 1 2 3 4 5
    

    The pop_front() and pop_back() Operations on Deque

    These operation is done when we need to remove elements from front or back. When we remove an element from the front of the deque, we need to increment the front pointer by one.

    Similarly, when we remove an element from the back of the deque, we need to decrement the rear pointer by one.

    Algorithm for pop_front() and pop_back()

    Following are the steps to remove an element from the front or back of the deque −

    1. Check if the deque is empty.
    2. Remove the element from the front or back of the deque.
    3. Increment or decrement the front or rear pointer.
    4. Decrement the size of the deque.
    

    Implementation

    Following is the implementation of pop_front() and pop_back() operations on deque.

    CC++JavaPython

    //C Program#include <stdio.h>#include <stdlib.h>#define SIZE 5int deque[SIZE];int front =-1, rear =-1;// Check if the deque is fullintisFull(){return((front ==0&& rear == SIZE -1)||(front == rear +1));}// Check if the deque is emptyintisEmpty(){return(front ==-1);}// Insert element at the backvoidpush_back(int element){if(isFull()){printf("Deque is full\n");}else{if(front ==-1){// If deque is initially empty
             front = rear =0;}elseif(rear == SIZE -1){// Wrap around to the front
             rear =0;}else{
             rear++;}
          deque[rear]= element;printf("Inserted -> %d\n", element);}}// Remove element from the frontvoidpop_front(){if(isEmpty()){printf("Deque is empty\n");}else{printf("Deleted from front -> %d\n", deque[front]);if(front == rear){// If only one element is present
             front = rear =-1;}else{
             front =(front +1)% SIZE;}}}// Remove element from the backvoidpop_back(){if(isEmpty()){printf("Deque is empty\n");}else{printf("Deleted from back -> %d\n", deque[rear]);if(front == rear){// If only one element is present
             front = rear =-1;}elseif(rear ==0){
             rear = SIZE -1;}else{
             rear--;}}}// Display the dequevoiddisplay(){if(isEmpty()){printf("Empty Deque\n");}else{printf("Elements -> ");int i = front;while(1){printf("%d ", deque[i]);if(i == rear)break;// Stop when the rear is reached
             i =(i +1)% SIZE;// Circular increment}printf("\n");}}// Main functionintmain(){push_back(1);push_back(2);push_back(3);push_back(4);push_back(5);pop_front();pop_back();display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Inserted -> 4
    Inserted -> 5
    Deleted -> 1
    Deleted -> 5
    

    The peek_front() and peek_back() Operations on Deque

    When we want to get the element from the front or back of the deque, we can use the peek_front() and peek_back() operations.

    Algorithm for peek_front() and peek_back()

    Following are the steps to get the element from the front or back of the deque −

    1. Check if the deque is empty.
    2. If not empty, return the element from the front or back of the deque.
    

    Implementation

    Following is the implementation code of peek_front() and peek_back() operations on deque.

    CC++JavaPython

    //C Program#include <stdio.h>#include <stdlib.h>#define SIZE 5int deque[SIZE];int front =-1, rear =-1;// Check if the deque is fullintisFull(){return((front ==0&& rear == SIZE -1)||(front == rear +1));}// Check if the deque is emptyintisEmpty(){return(front ==-1);}// Insert element at the backvoidpush_back(int element){if(isFull()){printf("Deque is full\n");}else{if(front ==-1){// If deque is initially empty
             front = rear =0;}elseif(rear == SIZE -1){// Wrap around to the front
             rear =0;}else{
             rear++;}
          deque[rear]= element;printf("Inserted -> %d\n", element);}}// Get the element from the frontintpeek_front(){if(isEmpty()){printf("Deque is empty\n");return-1;}else{return deque[front];}}// Get the element from the backintpeek_back(){if(isEmpty()){printf("Deque is empty\n");return-1;}else{return deque[rear];}}// Main functionintmain(){push_back(1);push_back(2);push_back(3);push_back(4);push_back(5);printf("\nElement at front: %d\n",peek_front());printf("Element at back: %d\n",peek_back());return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Inserted -> 4
    Inserted -> 5
    
    Element at front: 1
    Element at back: 5
    

    Time Complexity of Deque Operations

    The time complexity of the deque operations is as follows −

    • push_front(x) − O(1)
    • push_back(x) − O(1)
    • pop_front() − O(1)
    • pop_back() − O(1)
    • peek_front() − O(1)
    • peek_back() − O(1)

    Thus, the deque operations have a time complexity of O(1).

    Applications of Deque

    Some of the applications of deque are as follows −

    • Deque is used for undo operation in text editors.
    • It is also used in implementation of the sliding window algorithm.
    • Deque is used in implementing the data structures like double-ended priority queue and double-ended stack.

    In summary, we use deque when we need to perform insertion and deletion operations at both ends of the data structure.

  • Data Structure – Priority Queue

    Overview

    Priority Queue is more specialized data structure than Queue. Like ordinary queue, priority queue has same method but with a major difference. In Priority queue items are ordered by key value so that item with the lowest value of key is at front and item with the highest value of key is at rear or vice versa. So we’re assigned priority to item based on its key value. Lower the value, higher the priority. Following are the principal methods of a Priority Queue.

    Basic Operations

    • insert / enqueue − add an item to the rear of the queue.
    • remove / dequeue − remove an item from the front of the queue.

    Priority Queue Representation

    Queue

    We’re going to implement Queue using array in this article. There is few more operations supported by queue which are following.

    • Peek − get the element at front of the queue.
    • isFull − check if queue is full.
    • isEmpty − check if queue is empty.

    Insert / Enqueue Operation

    Whenever an element is inserted into queue, priority queue inserts the item according to its order. Here we’re assuming that data with high value has low priority.

    Insert Operation
    voidinsert(int data){int i =0;if(!isFull()){// if queue is empty, insert the data if(itemCount ==0){
             intArray[itemCount++]= data;}else{// start from the right end of the queue for(i = itemCount -1; i >=0; i--){// if data is larger, shift existing item to right end if(data > intArray[i]){
                   intArray[i+1]= intArray[i];}else{break;}}// insert the data 
             intArray[i+1]= data;
             itemCount++;}}}

    Remove / Dequeue Operation

    Whenever an element is to be removed from queue, queue get the element using item count. Once element is removed. Item count is reduced by one.

    Queue Remove Operation
    intremoveData(){return intArray[--itemCount];}

    Demo Program

    PriorityQueueDemo.c

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int itemCount =0;intpeek(){return intArray[itemCount -1];}
    
    bool isEmpty(){return itemCount ==0;}
    
    bool isFull(){return itemCount == MAX;}intsize(){return itemCount;}voidinsert(int data){int i =0;if(!isFull()){// if queue is empty, insert the data if(itemCount ==0){
             intArray[itemCount++]= data;}else{// start from the right end of the queue for(i = itemCount -1; i >=0; i--){// if data is larger, shift existing item to right end if(data > intArray[i]){
                   intArray[i+1]= intArray[i];}else{break;}}// insert the data 
             intArray[i+1]= data;
             itemCount++;}}}intremoveData(){return intArray[--itemCount];}intmain(){/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);// ------------------// index : 0  1 2 3 4 // ------------------// queue : 12 9 5 3 1 insert(15);// ---------------------// index : 0  1 2 3 4  5 // ---------------------// queue : 15 12 9 5 3 1if(isFull()){printf("Queue is full!\n");}// remove one item int num =removeData();printf("Element removed: %d\n",num);// ---------------------// index : 0  1  2 3 4 // ---------------------// queue : 15 12 9 5 3  // insert more itemsinsert(16);// ----------------------// index :  0  1 2 3 4  5// ----------------------// queue : 16 15 12 9 5 3// As queue is full, elements will not be inserted. insert(17);insert(18);// ----------------------// index : 0   1  2 3 4 5// ----------------------// queue : 16 15 12 9 5 3printf("Element at front: %d\n",peek());printf("----------------------\n");printf("index : 5 4 3 2  1  0\n");printf("----------------------\n");printf("Queue:  ");while(!isEmpty()){int n =removeData();printf("%d ",n);}}

    If we compile and run the above program then it would produce following result −

    Queue is full!
    Element removed: 1
    Element at front: 3
    ----------------------
    index : 5 4 3 2 1 0
    ----------------------
    Queue: 3 5 9 12 15 16
  • Circular Queue Data Structure

    A queue is an abstract data structure that contains a collection of elements. Queue implements the FIFO mechanism i.e the element that is inserted first is also deleted first.

    Queue can be one linear data structure. But it may create some problem if we implement queue using array. Sometimes by using some consecutive insert and delete operation, the front and rear position will change. In that moment, it will look like the queue has no space to insert elements into it.

    Even if there are some free spaces, that will not be used due to some logical problems. To overcome this problem, we will use the circular queue data structure.

    What is Circular Queue?

    A circular queue is a type of queue in which the last position is connected back to the first position to make a circle. It is also known as a Ring Buffer. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. But using a circular queue, we can use the space to insert elements.

    It is a linear data structure that follows the FIFO mechanism. The circular queue is a more efficient way to implement a queue in a fixed size array. In a circular queue, the last element points to the first element making a circular link.

    Representation of Circular Queue

    Following is the representation of a circular queue, where the front is the index of the first element, and the rear is the index of the last element.

    Circular Queue

    Operations on Circular Queue

    There are mainly four operations that can be performed on a circular queue:

    • Enqueue: Insert an element into the circular queue.
    • Dequeue: Delete an element from the circular queue.
    • Front: Get the front element from the circular queue.
    • Rear: Get the last element from the circular queue.

    Circular Queue using Array

    Following is the implementation of a circular queue using an array:

    Enqueue Operation on Circular Queue

    Enqueue operation is used for inserting an element into the circular queue. The steps to perform the enqueue operation are as follows:

    Algorithm for Enqueue Operation

    Following are the steps to perform the enqueue operation on a circular queue:

    1.Initialize an array or any data structure to store the elements of the circular queue.
    2.Initialize two variables front and rear.
    3.Check if the circular queue is full.
    4.If it is not full, and if the front is -1, set the front to 0.
    5.Increment the rear by 1 and store it in the rear index.
    6.Update the rear index using rear = (rear + 1) % SIZE.
    

    We have provided the implementation of Enqueue operation on a circular queue using C, C++, Java, and Python. You can choose the language of your choice and view the code.

    CC++JavaPython

    //C Program#include <stdio.h>#define SIZE 5int items[SIZE];int front =-1, rear =-1;// Check if the queue is fullintisFull(){if((front == rear +1)||(front ==0&& rear == SIZE-1))return1;return0;}// Check if the queue is emptyintisEmpty(){if(front ==-1)return1;return0;}// Adding an elementvoidenQueue(int element){if(isFull())printf("\n Queue is full!! \n");else{if(front ==-1) front =0;
          rear =(rear +1)% SIZE;
          items[rear]= element;printf("\n Inserted -> %d", element);}}// Display the queuevoiddisplay(){int i;if(isEmpty())printf(" \n Empty Queue\n");else{printf("\n Items -> ");for(i = front; i!=rear; i=(i+1)%SIZE){printf("%d ",items[i]);}printf("%d ",items[i]);}}intmain(){enQueue(1);enQueue(2);enQueue(3);enQueue(4);enQueue(5);display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Inserted -> 4
    Inserted -> 5 
    Items -> 1 2 3 4 5   
    

    Dequeue Operation on Circular Queue

    Dequeue operation is used for deleting an element from the circular queue. The steps to perform the dequeue operation are as follows:

    Algorithm for Dequeue Operation

    Following are the steps to perform the dequeue operation on a circular queue:

    1.Check if the circular queue is empty.
    2.If the queue is not empty, store the element at the front index.
    3.If the front and rear are equal, set the front and rear to -1.
    4.Else, increase the front index by 1 using the formula front = (front + 1) % SIZE.
    5.At last print the deleted element.
    

    We have provided the implementation of Dequeue operation on a circular queue using C, C++, Java, and Python. You can choose the language of your choice and view the code.

    Code for Dequeue Operation in Circular Queue

    Following are the programs to remove a element from the circular queue −

    CC++JavaPython

    #include <stdio.h>#define SIZE 5int items[SIZE];int front =-1, rear =-1;// Check if the queue is fullintisFull(){if((front == rear +1)||(front ==0&& rear == SIZE-1))return1;return0;}// Check if the queue is emptyintisEmpty(){if(front ==-1)return1;return0;}// Adding an elementvoidenQueue(int element){if(isFull())printf("\n Queue is full!! \n");else{if(front ==-1) front =0;
          rear =(rear +1)% SIZE;
          items[rear]= element;printf("\n Inserted -> %d", element);}}// Deleting an elementintdeQueue(){int element;if(isEmpty()){printf("\n Queue is empty!! \n");return(-1);}else{
          element = items[front];if(front == rear){
             front =-1;
             rear =-1;}else{
             front =(front +1)% SIZE;}printf("\n Deleted element -> %d \n", element);return(element);}}// Display the queuevoiddisplay(){int i;if(isEmpty())printf(" \n Empty Queue\n");else{printf("\n Items -> ");for(i = front; i!=rear; i=(i+1)%SIZE){printf("%d ",items[i]);}printf("%d ",items[i]);}}intmain(){enQueue(1);enQueue(2);enQueue(3);display();deQueue();display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 1
    Inserted -> 2
    Inserted -> 3
    Items -> 1 2 3
    Deleted element -> 1
    Items -> 2 3
    

    Front Operation on Circular Queue

    Front operation is used to get the front element from the circular queue. The steps to perform the front operation are as follows:

    Algorithm for Front Operation

    1.Check if the circular queue is empty.
    2.If not empty, print the front index element/
    

    We have provided the implementation of Front operation on a circular queue using C, C++, Java, and Python. You can choose the language of your choice and view the code.

    Code for Front Operation in Circular Queue

    Following are the programs to look at the front element of the circular queue −

    CC++JavaPython

    #include <stdio.h>#define SIZE 5int items[SIZE];int front =-1, rear =-1;// Check if the queue is fullintisFull(){if((front == rear +1)||(front ==0&& rear == SIZE-1))return1;return0;}// Check if the queue is emptyintisEmpty(){if(front ==-1)return1;return0;}// Adding an elementvoidenQueue(int element){if(isFull())printf("\n Queue is full!! \n");else{if(front ==-1) front =0;
          rear =(rear +1)% SIZE;
          items[rear]= element;printf("\n Inserted -> %d", element);}}// Display the queuevoiddisplay(){int i;if(isEmpty())printf(" \n Empty Queue\n");else{printf("\n Front -> %d ",front);printf("\n Items -> ");for(i = front; i!=rear; i=(i+1)%SIZE){printf("%d ",items[i]);}printf("%d ",items[i]);}}intmain(){enQueue(1);enQueue(2);enQueue(3);display();return0;}

    Output

    The output obtained is as follows −

     Inserted -> 1
     Inserted -> 2
     Inserted -> 3
     Front -> 0 
     Items -> 1 2 3
    

    Rear Operation on Circular Queue

    Rear operation is used to get the last element from the circular queue. The steps to perform the rear operation are as follows:

    Algorithm for Rear Operation

    1.Check if the circular queue is empty..
    2.If it is not empty, print the element at the rear index.
    

    We have provided the implementation of Rear operation on a circular queue using C, C++, Java, and Python. You can choose the language of your choice and view the code.

    Code for Rear Operation in Circular Queue

    Following are the programs to looka at the rear element−

    CC++JavaPython

    #include <stdio.h>#define SIZE 5int items[SIZE];int front =-1, rear =-1;// Check if the queue is fullintisFull(){if((front == rear +1)||(front ==0&& rear == SIZE-1))return1;return0;}// Check if the queue is emptyintisEmpty(){if(front ==-1)return1;return0;}// Adding an elementvoidenQueue(int element){if(isFull())printf("\n Queue is full!! \n");else{if(front ==-1) front =0;
          rear =(rear +1)% SIZE;
          items[rear]= element;printf("\n Inserted -> %d", element);}}// Display the queuevoiddisplay(){int i;if(isEmpty())printf(" \n Empty Queue\n");else{printf("\n Items -> ");for(i = front; i!=rear; i=(i+1)%SIZE){printf("%d ",items[i]);}printf("%d ",items[i]);printf("\n Rear -> %d \n",rear);}}intmain(){enQueue(1);enQueue(2);enQueue(3);display();return0;}

    Output

    The output obtained is as follows −

     Inserted -> 1
     Inserted -> 2
     Inserted -> 3 
     Items -> 1 2 3 
     Rear -> 2 
    

    Circular Queue using Linked List

    Following are the implementation of a circular queue using a linked list:

    CC++JavaPython

    //C Program#include <stdio.h>#include <stdlib.h>structNode{int data;structNode* link;};structNode* front =NULL;structNode* rear =NULL;// Check if the queue is emptyintisEmpty(){return front ==NULL;}// Adding an elementvoidenQueue(int value){structNode* newNode =(structNode*)malloc(sizeof(structNode));
       newNode->data = value;
       newNode->link =NULL;if(isEmpty()){
          front = newNode;}else{
          rear->link = newNode;}
       rear = newNode;
       rear->link = front;printf("\n Inserted -> %d", value);}// Deleting an elementintdeQueue(){int value;if(isEmpty()){printf("\n Queue is Empty!!");return-1;}else{structNode* temp = front;
           value = temp->data;if(front == rear){
              front = rear =NULL;}else{
              front = front->link;
              rear->link = front;}free(temp);return value;}}// Display the queuevoiddisplay(){structNode* temp = front;if(isEmpty()){printf("\n Queue is Empty!!\n");}else{printf("\n Front -> ");do{printf("%d ", temp->data);
               temp = temp->link;}while(temp != front);printf("\n");}}intmain(){enQueue(14);enQueue(22);enQueue(6);// Display elements present in the queueprintf("Initial Queue ");display();// Deleting elements from queueprintf("\nElement Removed = %d",deQueue());// Display elements present in the queueprintf("\nQueue after deletion an element: ");display();// Inserting elements to queueenQueue(9);//Showing the rear of the queueprintf("\nRear Element = %d", rear->data);enQueue(20);//Showing the front of the queueprintf("\nFront Element = %d", front->data);printf("\nFinal Queue ");display();return0;}

    Output

    The output obtained is as follows −

    Inserted -> 14
     Inserted -> 22
     Inserted -> 6Initial Queue 
     Front -> 14 22 6 
    
    Element Removed = 14
    Queue after deletion an element: 
     Front -> 22 6 
    
     Inserted -> 9
    Rear Element = 9
     Inserted -> 20
    Front Element = 22
    Final Queue 
     Front -> 22 6 9 20 
    

    Time Complexity of Circular Queue

    Following are the time complexities of the circular queue:

    • Enqueue Operation: The time complexity of the enQueue operation is O(1) as we can insert an element at the rear end of the queue in constant time.
    • Dequeue Operation: The time complexity of the deQueue operation is O(1) as we can delete an element from the front end of the queue in constant time.
    • Front Operation: The time complexity of the front operation is O(1) as we can get the front element of the queue in constant time.
    • Rear Operation: The time complexity of the rear operation is O(1) as we can get the rear element of the queue in constant time.

    Applications of Circular Queue

    Following are some of the applications of a circular queue:

    • Memory Management: Circular queues are used in memory management to manage the memory efficiently. It is used to allocate memory to the processes when they are in need of memory.
    • Buffer Management: These queues are also useful in buffer management. Consider a situation where data is produced at a faster rate than it is consumed. In such cases, a circular queue is used to store the data temporarily.
    • Operating System: Suppose your system has a lot of processes to execute. In such cases, for the better management of processes, the operating system uses a circular queue to allocate the CPU to the processes.
    • Traffic Management: Traffic singals are controlled by the circular queue. Let’s say there are three signals, red, yellow, and green. The signals are in a circular queue. When the green signal is on, the next signal will be yellow, and then red. This process will continue in a circular manner.
    • Multimedia Player: When we play songs in a multimedia player, the songs are played in a circular manner. Once the last song is played, the first song will be played next. This is done using a circular queue.

    In general, when certain tasks are repeated in a circular manner, a circular queue is used to manage the tasks efficiently. Also, when the data is produced at a faster rate than it is consumed, a circular queue is used to store the data temporarily.

  • Queue Data Structure

    What is a Queue?

    queue is a linear data structure where elements are stored in the FIFO (First In First Out) principle where the first element inserted would be the first element to be accessed. A queue is an Abstract Data Type (ADT) similar to stack, the thing that makes queue different from stack is that a queue is open at both its ends. The data is inserted into the queue through one end and deleted from it using the other end. Queue is very frequently used in most programming languages.

    car

    A real-world example of queue can be a single-lane one-way road, where the vehicle enters first, exits first. More real-world examples can be seen as queues at the ticket windows and bus-stops.

    Representation of Queues

    Similar to the stack ADT, a queue ADT can also be implemented using arrays, linked lists, or pointers. As a small example in this tutorial, we implement queues using a one-dimensional array.

    Representation of queues

    Basic Operations in Queue

    Queue operations also include initialization of a queue, usage and permanently deleting the data from the memory.

    The most fundamental operations in the queue ADT include: enqueue(), dequeue(), peek(), isFull(), isEmpty(). These are all built-in operations to carry out data manipulation and to check the status of the queue.

    Queue uses two pointers − front and rear. The front pointer accesses the data from the front end (helping in enqueueing) while the rear pointer accesses data from the rear end (helping in dequeuing).

    Queue Insertion Operation: Enqueue()

    The enqueue() is a data manipulation operation that is used to insert elements into the stack. The following algorithm describes the enqueue() operation in a simpler way.

    Algorithm

    1. START
    2. Check if the queue is full.
    3. If the queue is full, produce overflow error and exit.
    4. If the queue is not full, increment rear pointer to point 
       the next empty space.
    5. Add data element to the queue location, where the rear 
       is pointing.
    6. return success.
    7. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;
    bool isFull(){return itemCount == MAX;}
    bool isEmpty(){return itemCount ==0;}intremoveData(){int data = intArray[front++];if(front == MAX){
          front =0;}
       itemCount--;return data;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}
          intArray[++rear]= data;
          itemCount++;}}intmain(){insert(3);insert(5);insert(9);insert(1);insert(12);insert(15);printf("Queue: ");while(!isEmpty()){int n =removeData();printf("%d ",n);}}

    Output

    Queue: 3 5 9 1 12 15
    

    Queue Deletion Operation: dequeue()

    The dequeue() is a data manipulation operation that is used to remove elements from the stack. The following algorithm describes the dequeue() operation in a simpler way.

    Algorithm

    1. START
    2. Check if the queue is empty.
    3. If the queue is empty, produce underflow error and exit.
    4. If the queue is not empty, access the data where front 
       is pointing.
    5. Increment front pointer to point to the next available 
       data element.
    6. Return success.
    7. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;
    bool isFull(){return itemCount == MAX;}
    bool isEmpty(){return itemCount ==0;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}
          intArray[++rear]= data;
          itemCount++;}}intremoveData(){int data = intArray[front++];if(front == MAX){
          front =0;}
       itemCount--;return data;}intmain(){int i;/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);insert(15);printf("Queue: ");for(i =0; i < MAX; i++)printf("%d ", intArray[i]);// remove one itemint num =removeData();printf("\nElement removed: %d\n",num);printf("Updated Queue: ");while(!isEmpty()){int n =removeData();printf("%d ",n);}}

    Output

    Queue: 3 5 9 1 12 15 
    Element removed: 3
    Updated Queue: 5 9 1 12 15 
    

    Queue – The peek() Operation

    The peek() is an operation which is used to retrieve the frontmost element in the queue, without deleting it. This operation is used to check the status of the queue with the help of the pointer.

    Algorithm

    1. START
    2. Return the element at the front of the queue
    3. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;intpeek(){return intArray[front];}
    bool isFull(){return itemCount == MAX;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}
          intArray[++rear]= data;
          itemCount++;}}intmain(){int i;/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);insert(15);printf("Queue: ");for(i =0; i < MAX; i++)printf("%d ", intArray[i]);printf("\nElement at front: %d\n",peek());}

    Output

    Queue: 3 5 9 1 12 15 
    Element at front: 3
    

    Queue – The isFull() Operation

    The isFull() operation verifies whether the stack is full.

    Algorithm

    1. START
    2. If the count of queue elements equals the queue size,
       return true
    3. Otherwise, return false
    4. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;
    bool isFull(){return itemCount == MAX;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}
          intArray[++rear]= data;
          itemCount++;}}intmain(){int i;/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);insert(15);printf("Queue: ");for(i =0; i < MAX; i++)printf("%d ", intArray[i]);printf("\n");if(isFull()){printf("Queue is full!\n");}}

    Output

    Queue: 3 5 9 1 12 15 
    Queue is full!
    

    Queue – The isEmpty() operation

    The isEmpty() operation verifies whether the stack is empty. This operation is used to check the status of the stack with the help of top pointer.

    Algorithm

    1. START
    2. If the count of queue elements equals zero, return true
    3. Otherwise, return false
    4. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;
    bool isEmpty(){return itemCount ==0;}intmain(){int i;printf("Queue: ");for(i =0; i < MAX; i++)printf("%d ", intArray[i]);printf("\n");if(isEmpty()){printf("Queue is Empty!\n");}}

    Output

    Queue: 0 0 0 0 0 0 
    Queue is Empty!
    

    Queue Complete Implementation

    Following are the complete implementations of Queue in various programming languages −

    CC++JavaPython

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;intpeek(){return intArray[front];}
    bool isEmpty(){return itemCount ==0;}
    bool isFull(){return itemCount == MAX;}intsize(){return itemCount;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}
          intArray[++rear]= data;
          itemCount++;}}intremoveData(){int data = intArray[front++];if(front == MAX){
          front =0;}
       itemCount--;return data;}intmain(){/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);insert(15);printf("Queue size: %d",size());printf("\nQueue: ");for(int i =0; i < MAX; i++){printf("%d ", intArray[i]);}if(isFull()){printf("\nQueue is full!");}// remove one itemint num =removeData();printf("\nElement removed: %d", num);printf("\nSize of Queue after deletion: %d",size());printf("\nElement at front: %d",peek());}

    Output

    Queue size: 6
    Queue: 3 5 9 1 12 15
    Queue is full!
    Element removed: 3
    Size of Queue after deletion: 5
    Element at front: 5

    Queue Implementation in C

    check the implementation of Queue Program using C

    We shall see the queue implementation in C programming language here. To learn the theory aspect of queue, click on visit previous page.

    Queue Implementation in C

    #include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#define MAX 6int intArray[MAX];int front =0;int rear =-1;int itemCount =0;intpeek(){return intArray[front];}
    
    bool isEmpty(){return itemCount ==0;}
    
    bool isFull(){return itemCount == MAX;}intsize(){return itemCount;}voidinsert(int data){if(!isFull()){if(rear == MAX-1){
             rear =-1;}       
    
          intArray[&plus;&plus;rear]= data;
          itemCount&plus;&plus;;}}intremoveData(){int data = intArray[front&plus;&plus;];if(front == MAX){
          front =0;}
    	
       itemCount--;return data;}intmain(){/* insert 5 items */insert(3);insert(5);insert(9);insert(1);insert(12);// front : 0// rear  : 4// ------------------// index : 0 1 2 3 4 // ------------------// queue : 3 5 9 1 12insert(15);// front : 0// rear  : 5// ---------------------// index : 0 1 2 3 4  5 // ---------------------// queue : 3 5 9 1 12 15if(isFull()){printf("Queue is full!\n");}// remove one item int num =removeData();printf("Element removed: %d\n",num);// front : 1// rear  : 5// -------------------// index : 1 2 3 4  5// -------------------// queue : 5 9 1 12 15// insert more itemsinsert(16);// front : 1// rear  : -1// ----------------------// index : 0  1 2 3 4  5// ----------------------// queue : 16 5 9 1 12 15// As queue is full, elements will not be inserted. insert(17);insert(18);// ----------------------// index : 0  1 2 3 4  5// ----------------------// queue : 16 5 9 1 12 15printf("Element at front: %d\n",peek());printf("----------------------\n");printf("index : 5 4 3 2  1  0\n");printf("----------------------\n");printf("Queue:  ");while(!isEmpty()){int n =removeData();printf("%d ",n);}}

    Output

    If we compile and run the above program, it will produce the following result −

    Queue is full!
    Element removed: 3
    Element at front: 5
    ----------------------
    index : 5 4 3 2 1 0
    ----------------------
    Queue: 5 9 1 12 15 16
  • Expression Parsing in Data Structure

    An expression is any word or group of words or symbols that generates a value on evaluation. Parsing expression means analyzing the expression for its words or symbols depending on a particular criterion. Expression parsing is a term used in a programming language to evaluate arithmetic and logical expressions.

    The way to write arithmetic expression is known as a notation. An arithmetic expression can be written in three different but equivalent notations, i.e., without changing the essence or output of an expression. These notations are −

    • Infix Notation
    • Prefix (Polish) Notation
    • Postfix (Reverse-Polish) Notation

    These notations are named as how they use operator in expression. We shall learn the same here in this chapter.

    Infix Notation

    We write expression in infix notation, e.g. a – b &plus; c, where operators are used in-between operands. It is easy for us humans to read, write, and speak in infix notation but the same does not go well with computing devices. An algorithm to process infix notation could be difficult and costly in terms of time and space consumption.

    Prefix Notation

    In this notation, operator is prefixed to operands, i.e. operator is written ahead of operands. For example, &plus;ab. This is equivalent to its infix notation a &plus; b. Prefix notation is also known as Polish Notation.

    Postfix Notation

    This notation style is known as Reversed Polish Notation. In this notation style, the operator is postfixed to the operands i.e., the operator is written after the operands. For example, ab&plus;. This is equivalent to its infix notation a &plus; b.

    The following table briefly tries to show the difference in all three notations −

    Sr.No.Infix NotationPrefix NotationPostfix Notation
    1a &plus; b&plus; a ba b &plus;
    2(a &plus; b) ∗ c∗ &plus; a b ca b &plus; c ∗
    3a ∗ (b &plus; c)∗ a &plus; b ca b c &plus; ∗
    4a / b &plus; c / d&plus; / a b / c da b / c d / &plus;
    5(a &plus; b) ∗ (c &plus; d)∗ &plus; a b &plus; c da b &plus; c d &plus; ∗
    6((a &plus; b) ∗ c) – d– ∗ &plus; a b c da b &plus; c ∗ d –

    Parsing Expressions

    As we have discussed, it is not a very efficient way to design an algorithm or program to parse infix notations. Instead, these infix notations are first converted into either postfix or prefix notations and then computed.

    To parse any arithmetic expression, we need to take care of operator precedence and associativity also.

    Precedence

    When an operand is in between two different operators, which operator will take the operand first, is decided by the precedence of an operator over others. For example −

    Operator Precendence

    As multiplication operation has precedence over addition, b * c will be evaluated first. A table of operator precedence is provided later.

    Associativity

    Associativity describes the rule where operators with the same precedence appear in an expression. For example, in expression a &plus; b − c, both &plus; and − have the same precedence, then which part of the expression will be evaluated first, is determined by associativity of those operators. Here, both &plus; and − are left associative, so the expression will be evaluated as (a &plus; b) − c.

    Precedence and associativity determines the order of evaluation of an expression. Following is an operator precedence and associativity table (highest to lowest) −

    Sr.No.OperatorPrecedenceAssociativity
    1Exponentiation ^HighestRight Associative
    2Multiplication ( ∗ ) & Division ( / )Second HighestLeft Associative
    3Addition ( &plus; ) & Subtraction ( − )LowestLeft Associative

    The above table shows the default behavior of operators. At any point of time in expression evaluation, the order can be altered by using parenthesis. For example −

    In a &plus; b*c, the expression part b*c will be evaluated first, with multiplication as precedence over addition. We here use parenthesis for a &plus; b to be evaluated first, like (a &plus; b)*c.

    Postfix Evaluation Algorithm

    We shall now look at the algorithm on how to evaluate postfix notation −

    Step 1. Scan the expression from left to right 
    Step 2. If it is an operand push it to stack 
    Step 3. If it is an operator pull operand from stack and 
            perform operation 
    Step 4. Store the output of step 3, back to stack 
    Step 5. Scan the expression until all operands are consumed 
    Step 6. Pop the stack and perform operation
    

    Expression Parsing – Complete implementation

    Following are the complete implementations of Expression Parsing (Conversion from infix notations to postfix notations) in various programming languages −

    CC++JavaPython

    #include<stdio.h>#include<string.h>#include<ctype.h>//char stackchar stack[25];int top =-1;voidpush(char item){
       stack[++top]= item;}charpop(){return stack[top--];}//returns precedence of operatorsintprecedence(char symbol){switch(symbol){case'+':case'-':return2;break;case'*':case'/':return3;break;case'^':return4;break;case'(':case')':case'#':return1;break;}}//check whether the symbol is operator?intisOperator(char symbol){switch(symbol){case'+':case'-':case'*':case'/':case'^':case'(':case')':return1;break;default:return0;}}//converts infix expression to postfixvoidconvert(char infix[],char postfix[]){int i,symbol,j =0; 
       stack[++top]='#';for(i =0;i<strlen(infix);i++){
          symbol = infix[i];if(isOperator(symbol)==0){
             postfix[j]= symbol; 
             j++;}else{if(symbol =='('){push(symbol);}else{if(symbol ==')'){while(stack[top]!='('){
                      postfix[j]=pop(); 
                      j++;}pop();//pop out (. }else{if(precedence(symbol)>precedence(stack[top])){push(symbol);}else{while(precedence(symbol)<=precedence(stack[top])){
                         postfix[j]=pop(); 
                         j++;}push(symbol);}}}}}while(stack[top]!='#'){
          postfix[j]=pop(); 
          j++;} 
    	
       postfix[j]='\0';//null terminate string. }//int stackint stack_int[25];int top_int =-1;voidpush_int(int item){
       stack_int[++top_int]= item;}charpop_int(){return stack_int[top_int--];}//evaluates postfix expressionintevaluate(char*postfix){char ch;int i =0,operand1,operand2;while((ch = postfix[i++])!='\0'){if(isdigit(ch)){push_int(ch-'0');// Push the operand }else{//Operator,pop two  operands 
             operand2 =pop_int();
             operand1 =pop_int();switch(ch){case'+':push_int(operand1+operand2);break;case'-':push_int(operand1-operand2);break;case'*':push_int(operand1*operand2);break;case'/':push_int(operand1/operand2);break;}}}return stack_int[top_int];}voidmain(){char infix[25]="1*(2+3)",postfix[25];convert(infix,postfix);printf("Infix expression is: %s\n", infix);printf("Postfix expression is: %s\n", postfix);printf("Evaluated expression is: %d\n",evaluate(postfix));}

    Output

    Infix expression is: 1*(2+3)
    Postfix expression is: 123+*
    Evaluated expression is: 5 
  • Stack Data Structure

    What is a Stack?

    A stack is a linear data structure where elements are stored in the LIFO (Last In First Out) principle where the last element inserted would be the first element to be deleted. A stack is an Abstract Data Type (ADT), that is popularly used in most programming languages. It is named stack because it has the similar operations as the real-world stacks, for example − a pack of cards or a pile of plates, etc.

    stack example

    Stack is considered a complex data structure because it uses other data structures for implementation, such as Arrays, Linked lists, etc.

    Stack Representation

    A stack allows all data operations at one end only. At any given time, we can only access the top element of a stack.

    The following diagram depicts a stack and its operations −

    Stack Representation

    A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can either be a fixed size one or it may have a sense of dynamic resizing. Here, we are going to implement stack using arrays, which makes it a fixed size stack implementation.

    Basic Operations on Stacks

    Stack operations are usually performed for initialization, usage and, de-initialization of the stack ADT.

    The most fundamental operations in the stack ADT include: push(), pop(), peek(), isFull(), isEmpty(). These are all built-in operations to carry out data manipulation and to check the status of the stack.

    Stack uses pointers that always point to the topmost element within the stack, hence called as the top pointer.

    Stack Insertion: push()

    The push() is an operation that inserts elements into the stack. The following is an algorithm that describes the push() operation in a simpler way.

    Algorithm

    1. Checks if the stack is full.
    2. If the stack is full, produces an error and exit.
    3. If the stack is not full, increments top to point next 
        empty space.
    4. Adds data element to the stack location, where top 
        is pointing.
    5. Returns success.
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is full*/intisfull(){if(top == MAXSIZE)return1;elsereturn0;}/* Function to insert into the stack */intpush(int data){if(!isfull()){
          top = top +1;
          stack[top]= data;}else{printf("Could not insert data, Stack is full.\n");}}/* Main function */intmain(){int i;push(44);push(10);push(62);push(123);push(15);printf("Stack Elements: \n");// print stack datafor(i =0; i <8; i++){printf("%d ", stack[i]);}return0;}

    Output

    Stack Elements: 
    44 10 62 123 15 0 0 0 
    

    Note − In Java we have used to built-in method push() to perform this operation.

    Stack Deletion: pop()

    The pop() is a data manipulation operation which removes elements from the stack. The following pseudo code describes the pop() operation in a simpler way.

    Algorithm

    1. Checks if the stack is empty.
    2. If the stack is empty, produces an error and exit.
    3. If the stack is not empty, accesses the data element at 
       which top is pointing.
    4. Decreases the value of top by 1.
    5. Returns success.
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is empty */intisempty(){if(top ==-1)return1;elsereturn0;}/* Check if the stack is full*/intisfull(){if(top == MAXSIZE)return1;elsereturn0;}/* Function to delete from the stack */intpop(){int data;if(!isempty()){
          data = stack[top];
          top = top -1;return data;}else{printf("Could not retrieve data, Stack is empty.\n");}}/* Function to insert into the stack */intpush(int data){if(!isfull()){
          top = top +1;
          stack[top]= data;}else{printf("Could not insert data, Stack is full.\n");}}/* Main function */intmain(){int i;push(44);push(10);push(62);push(123);push(15);printf("Stack Elements: \n");// print stack datafor(i =0; i <8; i++){printf("%d ", stack[i]);}/*printf("Element at top of the stack: %d\n" ,peek());*/printf("\nElements popped: \n");// print stack datawhile(!isempty()){int data =pop();printf("%d ",data);}return0;}

    Output

    Stack Elements: 
    44 10 62 123 15 0 0 0 
    Elements popped: 
    15 123 62 10 44 
    

    Note − In Java we are using the built-in method pop().

    Retrieving topmost Element from Stack: peek()

    The peek() is an operation retrieves the topmost element within the stack, without deleting it. This operation is used to check the status of the stack with the help of the top pointer.

    Algorithm

    1. START
    2. return the element at the top of the stack
    3. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is full */intisfull(){if(top == MAXSIZE)return1;elsereturn0;}/* Function to return the topmost element in the stack */intpeek(){return stack[top];}/* Function to insert into the stack */intpush(int data){if(!isfull()){
          top = top +1;
          stack[top]= data;}else{printf("Could not insert data, Stack is full.\n");}}/* Main function */intmain(){int i;push(44);push(10);push(62);push(123);push(15);printf("Stack Elements: \n");// print stack datafor(i =0; i <8; i++){printf("%d ", stack[i]);}printf("\nElement at top of the stack: %d\n",peek());return0;}

    Output

    Stack Elements: 
    44 10 62 123 15 0 0 0 
    Element at top of the stack: 15
    

    Verifying whether the Stack is full: isFull()

    The isFull() operation checks whether the stack is full. This operation is used to check the status of the stack with the help of top pointer.

    Algorithm

    1. START
    2. If the size of the stack is equal to the top position of the stack,
       the stack is full. Return 1.
    3. Otherwise, return 0.
    4. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is full */intisfull(){if(top == MAXSIZE)return1;elsereturn0;}/* Main function */intmain(){printf("Stack full: %s\n",isfull()?"true":"false");return0;}

    Output

    Stack full: false
    

    Verifying whether the Stack is empty: isEmpty()

    The isEmpty() operation verifies whether the stack is empty. This operation is used to check the status of the stack with the help of top pointer.

    Algorithm

    1. START
    2. If the top value is -1, the stack is empty. Return 1.
    3. Otherwise, return 0.
    4. END
    

    Example

    Following are the implementations of this operation in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is empty */intisempty(){if(top ==-1)return1;elsereturn0;}/* Main function */intmain(){printf("Stack empty: %s\n",isempty()?"true":"false");return0;}

    Output

    Stack empty: true
    

    Stack Complete implementation

    Following are the complete implementations of Stack in various programming languages −

    CC++JavaPython

    #include <stdio.h>int MAXSIZE =8;int stack[8];int top =-1;/* Check if the stack is empty */intisempty(){if(top ==-1)return1;elsereturn0;}/* Check if the stack is full */intisfull(){if(top == MAXSIZE)return1;elsereturn0;}/* Function to return the topmost element in the stack */intpeek(){return stack[top];}/* Function to delete from the stack */intpop(){int data;if(!isempty()){
          data = stack[top];
          top = top -1;return data;}else{printf("Could not retrieve data, Stack is empty.\n");}}/* Function to insert into the stack */intpush(int data){if(!isfull()){
          top = top +1;
          stack[top]= data;}else{printf("Could not insert data, Stack is full.\n");}}/* Main function */intmain(){push(44);push(10);push(62);push(123);push(15);printf("Element at top of the stack: %d\n",peek());printf("Elements: \n");// print stack datawhile(!isempty()){int data =pop();printf("%d\n",data);}printf("Stack full: %s\n",isfull()?"true":"false");printf("Stack empty: %s\n",isempty()?"true":"false");return0;}

    Output

    Element at top of the stack: 15
    Elements: 
    15123
    62
    10
    44
    Stack full: false
    Stack empty: true