棧和隊列

棧(stack)和隊列(queue)都是動態集合,且在其上能進行delete操作所移除的元素是預先設定的。在棧中刪除的是最近插入的元素;在隊列中則是存在最久的元素。這兩者實現的分別是後進先出(last in, first out)先進先出(first in, first out)的策略。

數組表示

    利用數組表示一個簡單的棧和隊列確實是一個不錯的選擇,能夠理解棧和隊列對數據的操作即可。下面給出棧的數組表示;

struct Stack{
    int size;
    const static int N;
    int dat[N];
    int top;
    
    Stack(){
        top = 0;
        size = 0;
    }
    
    bool isEmpty(){
        return size == 0;
    }
    
    void push(int v){
        top++;
        dat[top] = v;
        size --;
    }
    
    int pop(){
        if(isEmpty())
            ;//error("underflow");
        else {
            top--;
            size--;
            return dat[top+1];
        }
    }
};

    如果利用一個數組表示兩個棧,並且當兩個棧中的元素個數和小於n的時候都不會溢出。這樣的數據結構可以將兩個棧的棧底分別設置在數組的兩端。然後兩個棧的top向中間靠攏。即可達到共享一個數組實現兩個棧的目的。代碼如下:

struct DoubleStack {
    const static int N = 1000;
    int dat[N];
    int top1, top2;
    int size1, size2;
    
    DoubleStack(){
        top1 = top2 = size1 = size2 = 0;
    }

    //flag == true -> stack1 ;flag==false -> stack2
    bool isEmpty(bool flag) {
        if(flag)
            return size1 == 0;
        else
            return size2 == 0;
    }

    bool isFlow() {
        return top1 + 1 == top2;
    }
    
    //flag == true -> stack1 ;flag==false -> stack2
    void push(bool flag, int v) {
        if(isFlow())
            return ;// error("overFlow");
        if(flag) {
            top1++;
            dat[top1] = v;
            size1++;
        } else {
            top2--;
            dat[top2] = v;
            size2++;
        }
    }

    //flag == true -> stack1 ;flag==false -> stack2
    int pop(bool flag) {
        if(isEmpty(flag))
            return -1;//error("underFlow");
        if(flag) {
            size1--;
            top1--;
            return dat[top1 + 1];
        } else {
            top2++;
            size2--;
            return dat[top2 - 1];
        }
    }

};

隊列(數組表示)

    隊列也可以利用數組表示,設置兩個數組下標表示隊首和隊尾,對其進行插入到隊尾和彈出隊首元素等操作。下面代碼tail指向的是隊尾元素的後面一個位置;

    

struct Queue{
    int size;
    const static int N = 1000;
    int dat[N];
    int tail, front;

    bool isEmpty(){
        return tail == front;
    }

    bool isFlow(){
        return tail + 1 == front;
    }

    Queue(){
        size = 0;
        tail = front = 1;
    }

    void enQueue(int v){
        if(isFlow())
            return ;// error("overFlow");
        dat[tail] = v;
        if(tail == N)
            tail = 1;
        else tail += 1;
        size++;
    }

    int deQueue(){
        if(isEmpty())
            return -1;//error("underFlow");
        int x = dat[front];
        if(front == N)
            front = 1;
        else front += 1;
        size --;
        return x;
    }

    int getSize() {
        return size;
    }

};

利用數組實現雙端隊列,就是可以隊首和隊尾都能進行插入刪除操作的結構。

struct Deque{
    int size;
    const static int N = 1000;
    int dat[N];
    int front, tail;

    Deque(){
        size = 0;
        front =  tail = 1;
    }

    bool isEmpty(){
        return tail == front;
    }

    bool isFlow(){
        return tail + 1 == front;
    }

    void push_back(int v){
        if(isFlow())
            return ;// error("overFlow");
        dat[tail] = v;
        if(tail == N)
            tail = 1;
        else tail += 1;
        size++;
    }

    int pop_back(){
        if(isEmpty())
            return -1;//error("underFlow");

        if(tail == 1)
            tail = N;
        else tail -= 1;
        int x = dat[tail];
        size --;
        return x;
    }

    void push_front(int v) {
        if(isFlow())
            return ;// error("overFlow");
        if(front == 1)
            front = N;
        else front -= 1;
        dat[front] = v;
        size++;
    }

    int pop_front(){
        if(isEmpty())
            return -1;//error("underFlow");
        int x = dat[front];
        if(front == N)
            front = 1;
        else front += 1;
        size --;
        return x;
    }
    
    int getSize()
    {
        return size;
    }
};

利用兩個隊列實現棧或者兩個棧實現隊列

    1. 利用兩個隊列實現棧: 因爲棧是LIFO, 而隊列是FIFO。 假設有兩個隊列q1、q2。將元素放入q1,當需要取最後進入的元素的時候可以q1中的前size-1個數取出放入q2.然後最夠一個元素返回即爲最後進入‘棧’的元素。可以利用隊列數組就是q1和q2對應Q[0]、Q[1]。這是可免去將元素有取出放回到q1中的操作。最後每一次取出一個棧的元素的操作爲O(size - 1) 。

    2. 利用兩個棧實現隊列。這個也是相同的道理,我們將元素壓入其中某個棧中,想要取出最先進入結構的元素需要將棧中的前size-1個元素取出放入另一個棧,然後彈出棧中剩下的最後一個元素就是最先進入結構中的元素。同樣可以利用滾動棧數組免去一些操作,最後時間複雜度爲O(size - 1)。 

    PS:這個複雜度是建立在棧和隊列插入和彈出的複雜度爲O(1)的前提下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章