隊列

基礎知識

先進先出。STL中與隊列對應的類模板爲queue ,常用操作:front()返回第一個元素;back()返回最後一個元素;push()向隊尾插入元素;pop()刪除第一個元素;empty()檢查容器是否爲空;size()返回容器的元素數。所有操作都在O(1)時間內完成。
關於隊列的實現方式,詳見: 棧與隊列-順序隊列與鏈隊列類模板的實現(數據結構基礎 第3周)

應用:兩個棧實現隊列

題目:用兩個棧實現一個隊列。請實現它的兩個函數appendTail和deleteHead,分別完成在隊列尾部插入節點和在隊列頭部刪除結點的功能。
分析:相關題目:用兩個隊列實現一個棧。
代碼實現

template<typename T> 
class CQueue {
public:
    CQueue(void);
    ~CQueue(void);

    void appendTail(const T& node);
    T deleteHead();
private:
    stack<T> stack1;
    stack<T> stack2;
};

template<typename T> 
CQueue<T>::CQueue(void) {}

template<typename T> 
CQueue<T>::~CQueue(void) {}

template<typename T> 
void CQueue<T>::appendTail(const T& node) {
    stack1.push(node);
}

template<typename T> 
T CQueue<T>::deleteHead() {
    if(stack2.empty()) {
        while(!stack1.empty()) {
            T data=stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }
    if(stack2.empty()) throw "The queue is empty.";
    T head=stack2.top();
    stack2.pop();
    return head;
}

測試用例

應用:滑動窗口的最大值

題目:給定一個數組和滑動窗口的大小,請找出所有滑動窗口裏的最大值。例如,如果輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小3,那麼一共存在6個滑動窗口,它們的最大值分別爲{4,4,6,6,6,5},如表8.3所示。
分析方法1,笨方法,老老實實滑動;方法2,對方法1找冗餘,一句話核心思想:維護一個隊列,一直保持隊列的頭元素爲滑動至當前位置時滑窗內的最大元素;方法3,我們實現過用O(1) 時間得到最大值的棧,也實現過用兩個棧實現隊列,把這兩者結合起來就是能夠在O(1) 時間獲得最大值的隊列。
代碼實現

//笨方法,時間複雜度$O(nk)$
int SlidingWindowMaximum_1(const vector<int>& input, int windowSize, vector<int>& result) {
    int dataSize = input.size();
    if (windowSize < 1) return 1;
    if (dataSize < windowSize) return 1;
    deque<int> cache(input.begin(), input.begin()+ windowSize-1);
    for (int i = windowSize - 1; i<dataSize; i++) {
        cache.push_back(input.at(i));
        result.push_back(*max_element(cache.begin(), cache.end()));   //此句時間複雜度爲O(K)
        cache.pop_front();
    }
    return 0;
}

//找冗餘,時間複雜度$O(n)$
//核心思想:維護一個隊列,一直保持隊列的頭元素爲滑動至位置i時滑窗內的最大元素。
int SlidingWindowMaximum_2(const vector<int>& input, int windowSize, vector<int>& result) {
    int dataSize = input.size();
    if (windowSize < 1) return 1;
    if (dataSize < windowSize) return 1;
    deque<int> cache(input.begin(), input.begin() + windowSize - 1);
    for (int i = windowSize - 1; i<dataSize; i++) {
        if (cache.size() >= windowSize) {           //隊列已滿
            cache.pop_front();                //取出第一個
            cache.push_back(input.at(i));
            cache.erase(cache.begin(), max_element(cache.begin(), cache.end()) );  //隊列中最大元素之前的元素已毫無意義
        }
        else {
            if (!cache.empty() && input.at(i) > cache.front()) {   //如果元素i大於隊列中的最大元素(即頭元素),則隊列中已存的所有元素已毫無意義。此處一定要判斷隊列是否爲空,要不然怎麼能取頭元素front()呢?
                cache.clear();              
            }
            cache.push_back(input.at(i));
        }
        result.push_back(cache.front());      //此句時間複雜度爲O(K)
    }
    return 0;
}

測試用例

vector<int> input = { 2, 3, 4, 2, 6, 2, 5, 1 };

應用:從上往下打印二叉樹

題目: 從上往下打印出二叉樹的每個結點,同一層的結點按照從左到右的順序打印。
分析: 也就是樹的層序遍歷了。
代碼實現

int SequenceTraversalByQueue(BinaryTreeNode* root) {
    if(!root) return 1;
    queue<BinaryTreeNode*> q;
    q.push(root);
    BinaryTreeNode* p=NULL;
    while(!q.emtpy()){
        p=q.front();
        cout << p->value << " ";
        if(p->left) q.push(p->left);
        if(p->right) q.push(p->right);
        q.pop();
    }
    return 0;
}
發佈了419 篇原創文章 · 獲贊 248 · 訪問量 125萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章