【用法詳解】C++-STL 隊列queue與優先隊列priority_queue的用法詳解與學習心得

【C++-STL 隊列與優先隊列用法詳解】html

一、隊列queueios

queue 模板類的定義在<queue>頭文件中。
與stack 模板類很類似,queue 模板類也須要兩個模板參數,一個是元素類型,一個容器類
型,元素類型是必要的,容器類型是可選的,默認爲deque 類型。
定義queue 對象的示例代碼以下:
queue<int> q1;
queue<double> q2;
queue 的基本操做有:
入隊,如例:q.push(x); 將x 接到隊列的末端。
出隊,如例:q.pop(); 彈出隊列的第一個元素,注意,並不會返回被彈出元素的值。
訪問隊首元素,如例:q.front(),即最先被壓入隊列的元素。
訪問隊尾元素,如例:q.back(),即最後被壓入隊列的元素。
判斷隊列空,如例:q.empty(),當隊列空時,返回true。
訪問隊列中的元素個數,如例:q.size()算法

【示例代碼1】less

#include <iostream>
#include <queue>
using namespace std;

int main() {
   int e,m;
    int len;
    queue<int> q;
    for(int i=0;i<10;i++){
        q.push(i);//入隊操做,q.push(x); 將x接到隊列的末端
    }

    if(!q.empty()){//q.empty(),當隊列空時,返回true
        cout<<"隊列非空"<<endl;
    }

    len=q.size();
    cout<<"隊列長度爲:"<<len<<endl;

    e=q.front();//q.front(),即最先被壓入隊列的元素
    m=q.back();//q.back(),即最後被壓入隊列的元素
    cout<<e<<" "<<m<<endl;

    q.pop();//出隊操做,q.pop(); 彈出隊列的第一個元素,注意,並不會返回被彈出元素的值
    e=q.front();
    cout<<e<<endl;

    for(int j=0;j<len-1;j++)//循環出隊
    {
        e=q.front();
        cout<<e<<" ";
        q.pop();
    }
    cout<<endl;
    return 0;
}

 

2、優先隊列函數

 

priority_queue<int> p;測試

【經常使用函數】  大數據

(1)priority_queue::empty
 判斷隊列是否爲空(也便是size是否爲0),是則返回true,不然返回false。優先隊列的此成員函數實際上調用底層容器的同名函數。
(2)priority_queue::size
 返回隊列中元素的個數。此函數實際上調用底層容器的同名函數。這個函數也能夠用於判斷隊列是否爲空。
(3)priority_queue::top
 返回隊頭元素的常引用,隊頭元素是在所設定的比較關係下最大也即優先級最高的元素。此函數實際上調用底層容器的front函數。
(4)priority_queue::pop
 清除隊頭元素。
(5)priority_queue::push給隊列插入元素,新元素會按其優先級被排列到適當位置。spa

q.size();//返回q裏元素個數
q.empty();//返回q是否爲空,空則返回1,不然返回0
q.push(k);//在q的末尾插入k
q.pop();//刪掉q的第一個元素
q.top();//返回q的第一個元素

3、less和greater優先隊列.net

 

  優先隊列是優先級高的在隊首,定義優先級大小的方式是傳入一個算子的參數比較a, b兩個東西,返回truea的優先級<b的優先級code

 

  默認是less算子也就是返回a<b,也就是小的優先級也小,而greater算子返回a>b,小的優先級高。

  若是是默認的less算子,值大的優先級高,天然默認的優先隊列大的先出隊。

  若是是使用greater算子,值小的優先級高,優先隊列小的先出隊。

priority_queue <int,vector<int>,less<int> > p;
priority_queue <int,vector<int>,greater<int> > q;

【默認less算子--優先輸出大數據】  

  priority_queue<Type, Container, Functional>模板類有三個模板參數,第一個Type是元素類型,第二個Container爲容器類型,第三個Functional是比較算子。其中後兩個均可以省略,默認容器爲vector,默認算子爲less:

  less算子即默認算子爲:大的往前排,小的日後排(出隊時隊列頭的元素出隊,即大者先出隊)。

#include<iostream>  
#include<queue>  
using namespace std;  
  
int main(){  
    priority_queue<int> p;  
    p.push(1);  
    p.push(2);  
    p.push(8);  
    p.push(5);  
    p.push(43);  
     while(!q.empty()){  
        cout<<p.top()<<endl;  
        p.pop();  
    }  
    return 0;  
}

【greater算子--優先輸出小數據】 

  greater算子即默認算子爲:小的往前排,大的日後排(出隊時隊列頭的元素出隊,即小者先出隊)。

priority_queue<int, vector<int>, greater<int> > p;
#include<iostream>  
#include<queue>  
using namespace std;  
  
int main(){  
    priority_queue<int, vector<int>, greater<int> >p;  
    p.push(1);  
    p.push(2);  
    p.push(8);  
    p.push(5);  
    p.push(43);  
    while(!q.empty()){  
        cout<<p.top()<<endl;  
        p.pop();  
    }  
    return 0;  
}

 

【自定義算子--重載默認的<符號】

 

#include <iostream>
#include <queue>
using namespace std;
class T
{
    public:
    int x, y, z;
    T(int a, int b, int c):x(a), y(b), z(c) { }

};

bool operator < (const T &t1, const T &t2)
{
    return t1.z < t2.z; // 按照z 的順序來決定t1 和t2 的順序
}


int main()
{
    priority_queue<T> q;//使用模板T的自定義比較方法
    q.push(T(4,4,3));
    q.push(T(2,2,5));
    q.push(T(1,5,4));
    q.push(T(3,3,6));
    while (!q.empty())
    {
        T t = q.top(); q.pop();
        cout << t.x << " " << t.y << " " << t.z << endl;

    }
    return 0;
}

我的更喜歡把自定義算子寫成友元的,寫進類裏:struct狀況相似

爲了更好地理解自定義算子,下面給出了兩個示例代碼,

其中一個爲上面例子中使用struct,且把自定義算子寫進struct內部的狀況

另外一個爲測試Dijkstra模板中HeapNode的測試代碼;

【源代碼1】    

#include <iostream>
#include <queue>
using namespace std;

struct T
{
    public:
    int x, y, z;
    T(int a, int b, int c):x(a), y(b), z(c) { }
    friend bool operator < (const T &t1, const T &t2)//自定義less算子,優先輸出大數據
    {   ////z值小的往前排,z值大的日後排(出隊時序列尾的元素出隊,即z值大者先出隊)
        return t1.z < t2.z; // 按照z 的順序來決定t1 和t2 的順序,優先輸出z值大的大數據
       // return t2.z > t1.z;
    }
};

int main()
{
    priority_queue<T> q;//使用模板T的自定義比較方法
    q.push(T(4,4,3));
    q.push(T(2,2,5));
    q.push(T(1,5,4));
    q.push(T(3,3,6));
    while (!q.empty())
    {
        T t = q.top();
        q.pop();
        cout << t.x << " " << t.y << " " << t.z << endl;

    }
    return 0;
}

【測試結果1】     

3 3 6
2 2 5
1 5 4
4 4 3

【源代碼2】     

#include <iostream>
#include <queue>
using namespace std;

struct HeapNode //Dijkstra算法用到的優先隊列的節點
{
    int d,u;
    HeapNode(int d,int u):d(d),u(u){}
    bool operator < (const HeapNode &rhs)const //自定義less算子,優先輸出大數據
    {   //按照d的順序來決定自身HeapNode和rhs的順序,優先輸出d值大的大數據
        //return d > rhs.d; 這兩種寫法是同樣的
         return rhs.d<d; //d值小的往前排,d值大的日後排(出隊時序列尾的元素出隊,即d值大者先出隊)
    }
};
int main()
{
    priority_queue<HeapNode> q;//使用模板T的自定義比較方法
    q.push(HeapNode(4,3));
    q.push(HeapNode(2,5));
    q.push(HeapNode(1,4));
    q.push(HeapNode(3,6));
    while (!q.empty())
    {
        HeapNode n = q.top(); q.pop();
        cout << n.d << " " << n.u << endl;

    }
    return 0;
}

【測試結果2】     

1 4
2 5
3 6
4 3

如下例子幫助理解大根堆、小根堆:

#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
 
int main(int argc, char** argv) { 
	//priority_queue<int,vector<int>,greater<int>>q;//greater是小根堆,從小到大輸出
	priority_queue<int,vector<int>,less<int>>q;     // less是大根堆, 從大到小輸出 
    //priority_queue<int>q默認從大到小排序(大根堆)
    int n;
    int x;
    while(cin>>n){
    	for(int i=0;i<n;i++){
    		cin>>x;
    		q.push(x);
		}
    	while(!q.empty()){
		    int x=q.top();
		    cout<<x<<" ";
		    q.pop();
	    }
	}

	return 0;
}

相關連接1

 

相關連接2

相關連接3