數據結構算法 - 棧和隊列

棧和隊列在數據結構和算法學習中,是比較容易理解的。但有時候感覺自己掌握了棧和隊列,可是在寫的時候遇到不同的情況,就不會處理了,因此自己還是想再總結回顧一下。

棧:
是一端受限,一端允許進行操作的線性表。即:先放的後取,後放的先取。就是我們通常說的“先進後出”(FILO)。存儲結構最常見的有兩種:一種是順序存儲,一種是鏈式存儲。其中順序存儲就是之前講的數組,鏈式存儲就是之前講的鏈表。

隊列:
像棧一樣,隊列也是一種線性表,它的特性是“先進先出”(FIFO),插入在一端,刪除在另一端。就像排隊一樣,剛來的人入隊(push)要排在隊尾,每次出隊(pop)的都是隊首的人。

具體的使用場景還是比較多的如:進制的轉換,中綴和後綴表達式,迷宮求解,文本編輯器,二叉樹遍歷等等,解決方案都需要用到棧和隊列的思想。下面我們就來寫一寫棧和隊列的實現。

/**
 * 判斷棧是否爲空
 */
template<class E>
bool Stack<E>::isEmpty() {
    return top == -1;
}

/**
 * 頂部元素彈棧
 */
template<class E>
E Stack<E>::pop() {
    assert(top >= 0);
    return array[top--];
}

/**
 * 獲取棧頂的元素
 */
template<class E>
E Stack<E>::peek() {
    assert(top >= 0);
    return array[top];
}

/**
 * 元素壓棧
 */
template<class E>
void Stack<E>::push(E e) {
    if (top + 1 == size) {
        growArray();
    }
    array[++top] = e;
}

/**
 * 擴容數組
 */
template<class E>
void Stack<E>::growArray() {
    size += size >> 1;
    array = (E *) realloc(array, size * sizeof(E));
}

用數組來實現一個棧挺簡單的,那如果用數組來實現一個隊列呢?隊列是先進先出的,那麼每次出隊列的時候我們需要移除第一個元素,因爲是存儲結構是數組,後面的元素就都需要往前面邏動,時間複雜度是 O(n)。這個時候我們不妨想一下有沒辦法可以不用邏動元素,將時間複雜度轉換爲 O(1) 級別的? 答案是:雙向數組

template<class E>
ArrayQueue<E>::ArrayQueue(int size) {
    // 確保數組的長度是 2 的冪次
    int init_size = 8;
    if (size >= init_size) {
        init_size = size;
        init_size |= init_size >> 1;
        init_size |= init_size >> 2;
        init_size |= init_size >> 4;
        init_size |= init_size >> 8;
        init_size |= init_size >> 16;
        init_size += 1;
    }
    array = (E *) malloc(sizeof(E) * init_size);
    this->size = init_size;
}

template<class E>
void ArrayQueue<E>::push(E e) {
    head = (head - 1) & (size - 1);
    array[head] = e;
    if (head == tail) {
        growArray();
    }
}

template<class E>
E ArrayQueue<E>::pop() {
    tail = (tail - 1) & (size - 1);
    return array[tail];
}

template<class E>
E ArrayQueue<E>::peek() {
    return array[(tail - 1) & (size - 1)];
}

template<class E>
bool ArrayQueue<E>::isEmpty() {
    return tail == head;
}

template<class E>
ArrayQueue<E>::~ArrayQueue() {
    delete[] array;
}
/**
* 開闢新的數組並調整元素循序
**/
template<class E>
void ArrayQueue<E>::growArray() {
    int new_size = size << 1;
    E *new_array = (E *) malloc(new_size * sizeof(E));

    // 把數組後面的元素邏動到前面
    int r = size - tail;
    copyArrayElement(array, head, new_array, 0, r);
    // 把數組前面的元素邏動到後面
    copyArrayElement(array, 0, new_array, r, head);
    // 釋放就內存
    free(array);
    array = new_array;
    // 重新改變指向
    head = 0;
    tail = size;
    size = new_size;
}

視頻鏈接:https://pan.baidu.com/s/1PC1ZBrtzjVB6VFShhLAagQ
視頻密碼:bmmt

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