天天看點

學習STL: 深入剖析queue容器

作者:鲨魚程式設計

Queue是一種FIFO(先進先出)資料結構,它允許在隊列的一端插入元素,并在另一端删除元素。在C++語言中,STL(标準模闆庫)中提供了一個queue容器,它提供了一種非常友善的方式來實作FIFO序列的管理。在本文中,我們将深入了解C++ STL queue容器,包括如何使用它、它的實作方式、操作和應用場景等方面的内容。

學習STL: 深入剖析queue容器

一、Queue容器的介紹

Queue是一種常見的資料結構,通常用于需要按照先進先出順序處理資料的場合。例如,一個列印隊列需要按照列印請求的順序列印檔案,一個網絡消息隊列需要按照接收消息的順序進行處理等等。Queue容器提供了一種友善的方式來管理這種FIFO序列。

C++ STL中的queue容器是一個模闆類,定義在<queue>頭檔案中。它是一個擴充卡容器,它基于另一個容器(預設情況下,deque容器)實作。Queue容器提供了兩個主要的操作:push()和pop()。push()在隊列的尾部插入一個元素;pop()從隊列的頭部删除一個元素。Queue容器還提供了一些其他的操作,如front()和back(),分别傳回隊列頭部和尾部的元素,以及empty()和size(),分别用于檢查隊列是否為空和擷取隊列中元素的數量。

一些重要的queue容器特性包括:

  1. 元素的通路:我們隻能通路隊列的頭部和尾部元素,不能通路隊列中的其他元素。
  2. 元素的插入和删除:插入操作隻能在隊列尾部進行,删除操作隻能在隊列頭部進行。

二、Queue容器的實作

Queue容器的實作方式通常基于一種雙端隊列(deque)資料結構,這種資料結構允許在隊列的頭部和尾部進行插入和删除操作。在C++ STL中,queue容器預設使用deque容器作為其底層實作,因為deque容器具有支援在兩端進行插入和删除操作的特點。

在queue容器中,push()操作用于在隊列的尾部插入一個元素,push()的實作方式如下所示:

void push(const T& value)
{
 c.push_back(value);
}           

其中,c是底層deque容器的一個執行個體,push_back()是deque容器的一個成員函數,用于在隊列的尾部插入一個元素。

pop()操作用于從隊列的頭部删除一個元素,pop()的實作方式如下所示:

void pop()
{
     c.pop_front();
}           

其中,pop_front()是deque容器的一個成員函數,用于從隊列的頭部删除一個元素。

front()操作用于傳回隊列頭部的元素,front()的實作方式如下所示:

T& front()
{
 return c.front();
}           

其中,front()是deque容器的一個成員函數,用于傳回隊列頭部的元素。

back()操作用于傳回隊列尾部的元素,back()的實作方式如下所示:

T& back()
{
 return c.back();
}           

其中,back()是deque容器的一個成員函數,用于傳回隊列尾部的元素。

empty()操作用于檢查隊列是否為空,empty()的實作方式如下所示:

bool empty() const
{
 return c.empty();
}           

其中,empty()是deque容器的一個成員函數,用于檢查隊列是否為空。

size()操作用于擷取隊列中元素的數量,size()的實作方式如下所示:

size_t size() const
{
 return c.size();
}           

其中,size()是deque容器的一個成員函數,用于擷取隊列中元素的數量。

三、Queue容器的操作

Queue容器提供了一些常用的操作,如push()、pop()、front()、back()、empty()和size()等。在下面的示例中,我們将示範如何使用這些操作來管理隊列。

首先,我們需要包含<queue>頭檔案,然後可以建立一個queue容器的執行個體,如下所示:

#include <queue>

std::queue<int> myQueue;           

這将建立一個空的int類型隊列myQueue。我們可以使用push()操作向隊列中插入元素,如下所示:

myQueue.push(10);
myQueue.push(20);
myQueue.push(30);           

這将在隊列的尾部依次插入三個元素10、20和30。我們可以使用front()操作擷取隊列頭部的元素,如下所示:

int frontElement = myQueue.front();           

這将擷取隊列頭部的元素10。我們可以使用pop()操作從隊列頭部删除一個元素,如下所示:

myQueue.pop();           

這将删除隊列頭部的元素10。我們可以使用back()操作擷取隊列尾部的元素,如下所示:

int backElement = myQueue.back();           

這将擷取隊列尾部的元素30。我們可以使用empty()操作檢查隊列是否為空,如下所示:

bool isEmpty = myQueue.empty();           

這将傳回false,因為隊列中仍有元素。最後,我們可以使用size()操作擷取隊列中元素的數量,如下所示:

size_t queueSize = myQueue.size();           

這将傳回隊列中元素的數量,這裡是2。

四. 進階用法

queue容器雖然功能簡單,但在很多程式設計場景中都非常有用。特别是在需要處理一系列任務,并且任務的處理順序需要嚴格按照它們到達的順序進行時,queue容器是理想的選擇。

例如,在多線程程式設計中,我們可以使用queue容器來實作任務隊列。以下是一個簡單的例子:

#include <queue>
#include <thread>
#include <mutex>

std::queue<int> tasks;  // 任務隊列
std::mutex mtx;  // 用于保護任務隊列的互斥鎖

void worker_thread()
{
    while (true)
    {
        std::unique_lock<std::mutex> lock(mtx);  // 擷取互斥鎖
        if (!tasks.empty())
        {
            int task = tasks.front();  // 擷取任務
            tasks.pop();  // 删除任務
            lock.unlock();  // 解鎖

            // 處理任務...
        }
        else
        {
            lock.unlock();  // 解鎖
            std::this_thread::yield();  // 沒有任務時,讓出CPU時間片
        }
    }
}           

在這個例子中,我們使用了queue容器來存儲待處理的任務,使用了mutex來保護queue容器在多線程環境下的安全。

五、總結

C++ STL中的queue容器是一個擴充卡容器,它提供了一種友善的方式來實作FIFO序列的管理。Queue容器基于雙端隊列(deque)資料結構實作,它提供了一些常用的操作,如push()、pop()、front()、back()、empty()和size()等。Queue容器通常用于需要按照先進先出順序處理資料的場合。在實際應用中,我們可以根據具體的需求選擇合适的資料結構來管理資料。

繼續閱讀