1. 程式人生 > >LeetCode622——設計迴圈佇列——c++根據不同STL容器的不同實現方式

LeetCode622——設計迴圈佇列——c++根據不同STL容器的不同實現方式

最開始呢還是先貼出題面。

設計你的迴圈佇列實現。 迴圈佇列是一種線性資料結構,其操作表現基於 FIFO(先進先出)原則並且隊尾被連線在隊首之後以形成一個迴圈。它也被稱為“環形緩衝器”。
迴圈佇列的一個好處是我們可以利用這個佇列之前用過的空間。在一個普通佇列裡,一旦一個佇列滿了,我們就不能插入下一個元素,即使在佇列前面仍有空間。但是使用迴圈佇列,我們能使用這些空間去儲存新的值。
你的實現應該支援如下操作:

  • MyCircularQueue(k): 構造器,設定佇列長度為 k 。
  • Front: 從隊首獲取元素。如果佇列為空,返回 -1 。
  • Rear: 獲取隊尾元素。如果佇列為空,返回 -1 。
  • enQueue(value): 向迴圈佇列插入一個元素。如果成功插入則返回真。
  • deQueue(): 從迴圈佇列中刪除一個元素。如果成功刪除則返回真。
  • isEmpty(): 檢查迴圈佇列是否為空。
  • isFull(): 檢查迴圈佇列是否已滿。

示例:

MyCircularQueue circularQueue = new MycircularQueue(3); // 設定長度為3

circularQueue.enQueue(1);  // 返回true

circularQueue.enQueue(2);  // 返回true

circularQueue.enQueue(3);  // 返回true

circularQueue.enQueue(4);  // 返回false,佇列已滿

circularQueue.Rear();  // 返回3

circularQueue.isFull();  // 返回true

circularQueue.deQueue();  // 返回true

circularQueue.enQueue(4);  // 返回true

circularQueue.Rear();  // 返回4

首先,我們考慮到要實現一個佇列,我們可以使用STL中組成佇列queue不同的Container,那麼很自然第一個想到的就是vector,根據vector的許多預置功能,我們可以很輕鬆的解決佇列的設計問題。

有一點需要注意的是 在使用erase()刪除元素時,()內的引數需要是以a.begin()作為下標0的迭代器引用~   下面貼出程式碼

class MyCircularQueue {
    private:
    vector<int> a;
    int max ;
public:
    /** Initialize your data structure here. Set the size of the queue to be k. */
    MyCircularQueue(int k) {

        max = k;
    }
    
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    bool enQueue(int value) {
        if(isFull())
        {
            return false;
        }
        else
        {
            a.push_back(value);
            return true;
        }
    }
    
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    bool deQueue() {
        
        if(isEmpty())
            return false;
        else
        {
            a.erase(a.begin());
            return true;
        }
    }
    
    /** Get the front item from the queue. */
    int Front() {
        if(isEmpty())
            return -1;
        else
        {
            return a.front();
        }
    }
    
    /** Get the last item from the queue. */
    int Rear() {
        if(isEmpty())
            return -1;
        else
        {
            int count = a.size();
            return a[count-1];
        }
    }
    
    /** Checks whether the circular queue is empty or not. */
    bool isEmpty() {
        if(a.size()==0)
            return true;
        else
            return false;
    }
    
    /** Checks whether the circular queue is full or not. */
    bool isFull() {
        if(a.size()==max)
            return true;
        else 
            return false;
    }
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue obj = new MyCircularQueue(k);
 * bool param_1 = obj.enQueue(value);
 * bool param_2 = obj.deQueue();
 * int param_3 = obj.Front();
 * int param_4 = obj.Rear();
 * bool param_5 = obj.isEmpty();
 * bool param_6 = obj.isFull();
 */

有了vector這種Container的使用思想之後,我們很自然的想到我們一般使用的佇列的真正預設Container——deque雙端佇列。那麼,通過閱讀雙端佇列的諸多函式,我們可以將這道題轉化到用deque來實現queue,這其實也是我們在使用STL中queue時的預設宣告:例如我們宣告 queue<int> a;,在<>中我們只聲明瞭佇列的資料型別,但其實還有第二個引數,只不過如果我們不特意加入的話他會預設宣告為<int, Container = deque>,即系統預設使用雙端佇列作為Container來宣告這個queue.

下面我們來看deque實現的程式碼,其實大同小異,只不過是替換了一些函式,操作同時變簡單了很多~

class MyCircularQueue {
    private:
    deque<int> a;
    int max ;
public:
    /** Initialize your data structure here. Set the size of the queue to be k. */
    MyCircularQueue(int k) {

        max = k;
    }
    
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    bool enQueue(int value) {
        if(isFull())
        {
            return false;
        }
        else
        {
            a.push_back(value);
            return true;
        }
    }
    
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    bool deQueue() {
        
        if(isEmpty())
            return false;
        else
        {
            a.pop_front();
            return true;
        }
    }
    
    /** Get the front item from the queue. */
    int Front() {
        if(isEmpty())
            return -1;
        else
        {
            return a.front();
        }
    }
    
    /** Get the last item from the queue. */
    int Rear() {
        if(isEmpty())
            return -1;
        else
        {
            return a.back();
        }
    }
    
    /** Checks whether the circular queue is empty or not. */
    bool isEmpty() {
        if(a.size()==0)
            return true;
        else
            return false;
    }
    
    /** Checks whether the circular queue is full or not. */
    bool isFull() {
        if(a.size()==max)
            return true;
        else 
            return false;
    }
};

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue obj = new MyCircularQueue(k);
 * bool param_1 = obj.enQueue(value);
 * bool param_2 = obj.deQueue();
 * int param_3 = obj.Front();
 * int param_4 = obj.Rear();
 * bool param_5 = obj.isEmpty();
 * bool param_6 = obj.isFull();
 */