Sunday 13 January 2013

Queue with push_rear(), pop_front() and get_min() in constant time


/*
This is a very good question. It took me good 2-3 hours to implement this.
push at rear and pop from front are O(1) operations, but to get minimum value is a really tough ask.
To implement this I used a separate queue, which is updated on push and pop operation to hold minimum value.
I have tested it in most scenarios but not all, if you find any scenario in which it will not work do let me know.
*/
#include<iostream.h>
#include<conio.h>
#include<process.h>
class Node
{
public:
      int data;
      Node *next;
       Node()
       {
                  next = NULL;
       }
       void initialiseNode(int val, Node *newNext)
       {
            data = val;
            next = newNext;
       }
};

class minimumQueue
{
public:
       Node *minFront;
       Node *minRear;
       minimumQueue()
       {
                 minFront = NULL;
                 minRear = NULL;
       }
     
       void minQueuePushRear(int val)
       {
            Node *newNode = new Node;
            newNode->data =val;
            if(minRear == NULL && minFront == NULL)
            {
                       minRear = newNode;
                       minFront = newNode;
            }
            else
            {
                minRear->next = newNode;
                minRear = minRear->next;
            }
       }
     
       void minQueuePopFront()
       {
            Node *ptr = minFront;
            if(minFront == minRear)
            {
                              minFront = NULL;
                              minRear = NULL;
            }
            else
            {
                minFront = minFront-> next;
            }
            delete ptr;
       }
};


class Queue
{
      Node *front ;
      Node *rear ;
      minimumQueue minQueue;
public:
       Queue()
       {
              front = NULL;
              rear = NULL;
       }
       bool isEmpty()
       {
            if(front == NULL && rear == NULL)
            {
                return true;
            }
            else
            {
                return false;
            }
       }
     
       void push_rear(int val)
       {
            Node *newNode = new Node;
            newNode->data = val;
            if(isEmpty())
            {
                front = newNode;
                rear = newNode;
                minQueue.minQueuePushRear(val);  
            }
            else
            {
                rear->next = newNode;
                rear = rear->next;
                if(minQueue.minRear->data > val)
                {
                                minQueue.minRear->data = val;
                }
                else
                {
                    minQueue.minQueuePushRear(val);
                }
                //this is later on added code
                if(val < minQueue.minFront->data)
                       minQueue.minFront->data = val;
            }
       }
       void pop_front()
       {
            Node *deleteFront = front;
            int val = front->data;
            if(front == rear)
            {
                front = NULL;
                rear = NULL;
            }
            else
            {
                front = front->next;
                if(val == minQueue.minFront->data)
                {
                    minQueue.minQueuePopFront();
                }
            }
            delete deleteFront;
       }
     
       void display()
       {
           for(Node *ptr = front; ptr != rear; ptr = ptr->next)
                    cout<<" "<<ptr->data;
           cout<<" "<<rear->data;
       }
     
       int get_min()
       {
           int value;
           if(minQueue.minFront == NULL)
                     value = -1;
           else if(minQueue.minFront->data > minQueue.minRear->data)
                                      value = minQueue.minRear->data;
           else
               value = minQueue.minFront->data;
           return value;
       }
     
     
};

int main()
{
    Queue q ;
    int choice,value,min;
    while(1)
    {
        system("CLS");
        cout<<"1. PUSH REAR\n2. POP FRONT\n3. GET MIN\n4. DISPLAY\n5. EXIT\n\nchoice?";
        cin>>choice;
        switch(choice)
        {
            case 1:
                 cout<<"Enter Value";
                 cin>>value;
                 q.push_rear(value);
                 break;
            case 2:
                 q.pop_front();
                 break;
            case 3:
                 min = q.get_min();
                 cout<<"\n Min is : "<<min;
                 getch();
                 break;
            case 4:
                 q.display();
                 getch();
                 break;
            case 5:
                 exit(0);
            default:
                    cout<<"Invalid Input";
        }
    }
}

2 comments:

  1. http://stackoverflow.com/questions/4802038/implement-a-queue-in-which-push-rear-pop-front-and-get-min-are-all-consta

    ReplyDelete
    Replies
    1. i guess this implementation is pretty simple

      Delete