1. 程式人生 > >優先佇列Priority Queues使用手冊

優先佇列Priority Queues使用手冊

優先佇列容器預設使用向量容器實現,使用者也可以使用雙端佇列容器。優先佇列總是把優先順序最高的元素放在佇列的最前方,來保持佇列的有序性。

插入操作push()使用一個雙變數的布林函式,將佇列中的元素重新排序,以滿足這個要求。

該函式可以由使用者提供,否則可以使用<操作符,元素越大,優先順序越高。

如果元素越小,優先順序越高,則需要使用函式物件greater,表明在決定向優先順序佇列中插入新元素時,push()應該使用的操作符是>而不是<.

 成員函式:

empty    
true if the priority queue has no elements

pop    
removes the top element of a priority queue

push    
adds an element to the end of the priority queue

size    
returns the number of items in the priority queue

top    
returns the top element of the priority queue

在優先佇列中,優先順序高的元素先出佇列。標準庫預設使用元素型別的<操作符來確定它們之間的優先順序關係。

優先佇列的第一種用法,也是最常用的用法:

priority_queue<int> qi;
通過<操作符可知在整數中元素大的優先順序高。

故示例1中輸出結果為:9 6 5 3 2

第二種方法:

在示例1中,如果我們要把元素從小到大輸出怎麼辦呢?

這時我們可以傳入一個比較函式,使用functional.h函式物件作為比較函式。

priority_queue<int, vector<int>, greater<int> > qi2;
其中

第二個引數為容器型別。

第三個引數為比較函式。

故示例2中輸出結果為:2 3 5 6 9

第三種方法:自定義優先順序。

struct node
{
    friend bool operator< (node n1, node n2)
    {
        return n1.priority < n2.priority;
    }
    int priority;
    int value;
};

在該結構中,value為值,priority為優先順序。

通過自定義operator<操作符來比較元素中的優先順序。

在示例3中輸出結果為:

優先順序  值

9          5

8          2

6          1

2          3

1          4

但如果結構定義如下:

struct node
{
    friend bool operator> (node n1, node n2)
    {
        return n1.priority > n2.priority;
    }
    int priority;
    int value;
};

則會編譯不過(G++編譯器)因為標準庫預設使用元素型別的<操作符來確定它們之間的優先順序關係。而且自定義型別的<操作符與>操作符並無直接聯絡,故會編譯不過。

//程式碼清單

#include<iostream>
#include<functional>
#include<queue>
using namespace std;
struct node
{
    friend bool operator< (node n1, node n2)
    {
        return n1.priority < n2.priority;
    }
    int priority;
    int value;
};
int main()
{
    const int len = 5;
    int i;
    int a[len] = {3,5,9,6,2};
    //示例1
    priority_queue<int> qi;
    for(i = 0; i < len; i++)
        qi.push(a[i]);
    for(i = 0; i < len; i++)
    {
        cout<<qi.top()<<" ";
        qi.pop();
    }
    cout<<endl;
    //示例2
    priority_queue<int, vector<int>, greater<int> >qi2;
    for(i = 0; i < len; i++)
        qi2.push(a[i]);
    for(i = 0; i < len; i++)
    {
        cout<<qi2.top()<<" ";
        qi2.pop();
    }
    cout<<endl;
    //示例3
    priority_queue<node> qn;
    node b[len];
    b[0].priority = 6; b[0].value = 1; 
    b[1].priority = 9; b[1].value = 5; 
    b[2].priority = 2; b[2].value = 3; 
    b[3].priority = 8; b[3].value = 2; 
    b[4].priority = 1; b[4].value = 4; 
    
    for(i = 0; i < len; i++)
        qn.push(b[i]);
    cout<<"優先順序"<<'\t'<<"值"<<endl;
    for(i = 0; i < len; i++)
    {
        cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;
        qn.pop();
    }
    return 0;
}

 另外貼一段優先佇列使用的程式碼:

#include<iostream>
#include<functional>
#include<queue>
#include<vector>
using namespace std;
 
 
struct cmp1
{
    bool operator () (int &a, int &b)
    {
        return a > b ;              // 從小到大排序,值 小的 優先級別高
    }
};
 
struct cmp2
{
    bool operator () (int &a, int &b)
    {
        return a < b;             // 從大到小
    }
};
 
struct number1
{
    int x;
    bool operator < (const number1 &a)const 
    {
        return x > a.x;         // 從小到大  ,x 小的 優先級別高
    }
};
 
struct number2
{
    int x;
    bool operator < (const number2 &a)const
    {
        return x < a.x;            // 從大到小  ,x 大的優先級別高
    }
};
 
int a[] = {14,10,56,7,83,22,36,91,3,47,72,0};
number1 num1[] ={14,10,56,7,83,22,36,91,3,47,72,0};
number2 num2[] ={14,10,56,7,83,22,36,91,3,47,72,0};
 
int main()
{
    priority_queue<int>que;  // 採用預設優先順序構造佇列  從大到小。 
 
    priority_queue<int, vector<int>, cmp1 >que1;
    priority_queue<int, vector<int>, cmp2 >que2;
 
    priority_queue<int, vector<int>, greater<int> > que3;  //functional 標頭檔案自帶的 
    priority_queue<int, vector<int>, less<int> > que4;      //functional 標頭檔案自帶的 
 
    priority_queue<number1> que5;
    priority_queue<number2> que6;
 
 
    int i;
    for(i=0;a[i];i++)
    {
        que.push(a[i]);
        que1.push(a[i]);
        que2.push(a[i]);
        que3.push(a[i]);
        que4.push(a[i]);
 
    }
 
     for(i=0;num1[i].x;i++)
         que5.push(num1[i]);
     for(i=0;num2[i].x;i++) 
         que6.push(num2[i]);
 
    printf("採用預設優先關係:\n(priority_queue<int>que;)\n");
    printf("Queue 0:\n");
        while(!que.empty())
    {
        printf("%3d",que.top());
        que.pop();
    }
    puts("");
    puts("");
    
    printf("採用結構體自定義優先順序方式一:\n(priority_queue<int,vector<int>,cmp>que;)\n");
    printf("Queue 1:\n");
    while(!que1.empty())
    {
        printf("%3d",que1.top());
        que1.pop();
    }
    puts("");
 
    printf("Queue 2:\n");
        while(!que2.empty())
    {
        printf("%3d",que2.top());
        que2.pop();
    }
    puts("");
    puts("");
 
    printf("採用標頭檔案\"functional\"內定義優先順序:\n(priority_queue<int, vector<int>,greater<int>/less<int> >que;)\n");
    printf("Queue 3:\n");
    while(!que3.empty())
    {
        printf("%3d",que3.top());
        que3.pop();
    }
    puts("");
 
    printf("Queue 4 :\n");
    while(!que4.empty())
    {
        printf("%3d",que4.top());
        que4.pop();
    }
    puts("");
    puts("");
 
    printf("採用結構體自定義優先順序方式二:\n(priority_queue<number>que)\n");
    printf("Queue 5:\n");
    while(!que5.empty())
    {
        printf("%3d",que5.top());
        que5.pop();
    }
    puts("");
 
    printf("Queue 6:\n");
    while(!que6.empty())
    {
        printf("%3d",que6.top());
        que6.pop();
    }
 
    return 0;
}

執行結果:

九月網易有道招聘上機題:

給出大小為N的陣列,用最快的辦法找出前M個大的數字。

#include <iostream>
#include <functional>
#include <queue>
 
using namespace std;
 
int main()
{
    priority_queue<int,vector<int>, greater<int> > q;//從小到大
    int n,m,num;
    while (cin>>n>>m)
    {
        int i;
        for (i = 0; i < m; i ++)
        {
            cin>>num;
            q.push(num);
        }
        for (; i < n; i ++)
        {
            cin>>num;
            if (num > q.top())
            {
                q.pop();
                q.push(num);
            }
        }
        while (!q.empty())
        {
            cout<<q.top()<<" ";
            q.pop();
        }
        cout<<endl;
    }
    return 0;
}
 

這個題目可以用一個大小是M的最小堆來實現,初始建堆用陣列前M個建好後,如果後面的元素a[i] 大於堆頂元素,那麼就刪除堆頂,插入新的元素。