和棧相反,隊列是FIFO表,先進先出。故名思議,和排隊打飯一樣,先入隊的先打完出去,而且只能從隊列的尾端加入(插隊的滾粗啊。。)。用數組實現隊列的話,循環隊列是一般是必須的。我們會用2個下標head and tail來標記隊頭和隊尾的位置,如果有人出隊的話,head就會+1,入隊tail+1,這樣整個隊列在數組中的位置就會慢慢向右移動,不做處理的話很快會到達數組的尾端。因此,循環隊列的采取這樣的操作,當隊頭或者隊尾超出存儲隊列的預設長度的話,就把他們置為0,等於再從數組的左邊開始向右增長,形成“卷繞”。
開始時,我們把head和tail初始化為0,這時的隊列是空的,此后我們也可以用head == tail 這條語句來判斷一個隊列是否為空。
NOTE:采用這種判斷條件的話,對於規模為N的數組來說只能規模為N - 1的隊列,因為如果此時再入隊一個對象,tail == head就成立了,意味着隊列為空,這不符合邏輯。
判斷隊列滿有兩種情況:
1. 此時head為0,tail = length - 1,意味着已經有N - 1個對象在隊列里。
2. head大於0,則隊列滿的條件為head = tail + 1,這種情況畫個圖就明白了,是由於“卷繞”造成的。
這是算法導論上的示意圖。下面貼下我簡單實現的代碼,C++寫的模板類
#ifndef _QUEUE_H_ #define _QUEUE_H_ template <class T> class Queue { private: int head; int tail; int length; T* array; public: Queue(){tail = head = length = 0;} Queue(int size); ~Queue(); bool isEmpty(); bool isFull(); void enQueue(T val); T deQueue(); }; template <class T> Queue<T>::Queue(int size) { tail = head = 0; length = size; array = new T[size]; } template <class T> Queue<T>::~Queue() { delete [] array; } template <class T> bool Queue<T>::isEmpty() { return head == tail; } template <class T> bool Queue<T>::isFull() { return (head == tail + 1) || (tail - head == length - 1); } template <class T> void Queue<T>::enQueue(T val) { if(isFull()) { std::cout << "Queue overflow!" << std::endl; /* exit or someting else */ } else { array[tail++] = val; if(tail == length) tail = 0; } } template <class T> T Queue<T>::deQueue() { T ret; if(isEmpty()) { std::cout << "Queue is empty!" << std::endl; /* exit or someting else */ } else { ret = array[head++]; if(head == length) head = 0; return ret; } } #endif
兩種最基本的線性表寫完了,過幾天回家寫個鏈表