棧和隊列在數據結構和算法學習中,是比較容易理解的。但有時候感覺自己掌握了棧和隊列,可是在寫的時候遇到不同的情況,就不會處理了,因此自己還是想再總結回顧一下。
棧:
是一端受限,一端允許進行操作的線性表。即:先放的後取,後放的先取。就是我們通常說的“先進後出”(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