您的位置:首页 > 编程语言 > C语言/C++

Priority_Queue 优先队列 C++学习笔记

2014-02-21 11:29 387 查看
priority_queue优先队列容器与队列一样,只能从队尾添加(插入)元素,从队头(队首)删除元素。但他有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似与给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认为按元素的值的由大到小排序;当然,可以重载“<”操作符来重新定义比较规则;

使用priority_queue需要声明头文件#include <queue>;

优先队列的使用方法

优先队列包含入队push()(插入元素),出队pop()(删除元素),读取队头元素top(),判断队列是否为空empty()和读取队列元素数量size()等方法;
下例程序具体说明了优先队列的使用方法:
#include <iostream>
#include <queue>
using namespace std;

int main(int argc, char *argv[])
{
    //定义优先队列对象,元素类型为整型;
    priority_queue <int> pq;
    //入队,插入新的元素;
    pq.push(1);
    pq.push(2);
    pq.push(3);
    pq.push(9);
    //返回队列中元素的个数;
    cout << pq.size() << endl;
    while(!pq.empty()) {  // == pq.empty!=true;
        //读取当前队首元素;
        cout << pq.top() << " ";
        //出队,删除队首元素;
        pq.pop();
    }
    cout << endl;
    return 0;
}

运行结果为:
4
9 3 2 1

重载“<”操作符来定义优先级

如果优先队列的元素类型是结构体,可以通过在结构体中重载“<”操作符的方法来修改优先队列的优先性;

下例程序详细说明了在结构体中重载“<”操作符的方法;

运行结果为:

Bomi 18.5

Jack 68.5

Peti 90

#include <iostream>

#include <queue>

#include <cstdio>

using namespace std;

struct Info

{

    string name;

    float score;

    //重载"<"操作符,指定优先级;

    bool operator < (const Info &a) const

    {

        //按score由小到大排列,如果要由大到小排列,使用“>”即可;

        return a.score < score;

    }

};

int main(int argc, char *argv[])

{

    freopen("data.in", "r", stdin);

    freopen("data.out", "w", stdout);

    //定义优先队列对象,元素类型为Info结构体型;

    priority_queue <Info> pq;

    Info info;  //定义结构体变量;

    //入队;

    info.name = "Jack";

    info.score = 68.5;

    pq.push(info);

    info.name = "Bomi";

    info.score = 18.5;

    pq.push(info);

    info.name = "Peti";

    info.score = 90;

    pq.push(info);

    //元素出队;

    while(!pq.empty()) {

        //返回队首元素;

        cout << pq.top().name << " " << pq.top().score << endl;

        //将队头元素弹出;

        pq.pop();

    }

    return 0;

}

重载“()”操作符来定义优先级

如果优先队列的元素不是结构体类型,则可以通过重载“()”操作符的方式来定义优先级,当然,元素是结构体类型,也可以通过重载“()”操作符的方法来定义优先级,而不是一定要在结构体内重载“<”操作符才行;

下例程序说明了重载“()”操作符的方法:

运行结果为:

1 5 9 28 34

#include <iostream>

#include <queue>

using namespace std;

//重载“()”操作符;

struct mycmp

{

    bool operator () (const int &a, const int &b)

    {

        //由小到大排列采用">"号,如果要由大到小排列,则采用"<"号;

        return a > b;

    }

};

int main(int argc, char *argv[])

{

    //定义优先队列,元素类型为Info的结构体,显式说明内部结构是vector;

    priority_queue <int, vector<int>, mycmp> pq;

    //入队;

    pq.push(1);

    pq.push(28);

    pq.push(9);

    pq.push(5);

    pq.push(34);

    //元素全部出队;

    while(!pq.empty()) {

        //返回队首元素;

        cout << pq.top() << " ";

        //删除队首元素;

        pq.pop();

    }

    cout << endl;

    return 0;

}

Windows 消息队列 ZOJ 2724

//ZheJiang University Local Contest 2006

消息队列是Windows操作系统的基石,对于每一个进程,系统维持了一个消息队列,如果一个进程发生了某一事件,如单击鼠标,文本改变,系统将增加一个消息到队列里,同时,如果队列里不是空的,那么,进程将一直循环的从队列里按优先值抓取消息,注意,数值小意味着高的优先级,在本题中,要求你模拟消息队列,把消息放到消息队列中,或从消息队列里抓取消息;

输入描述:

只有一个测试案例,每行是一条命令,“GET”或“PUT”表示从消息队列里抓取消息或把消息放入消息队列。如果是“PUT”命令,后面跟着一个字符串(表示消息名称)和两个整数(分别表示消息的参数和优先级),案例中的命令最多达60000条,注意,一条命令可以重复出现多次,如果两条命令的优先级相同,则先进入消息队列的那条先被处理;一直处理到文件结尾;

输出描述:对于每条“GET”指令,直接输出他抓取的消息的名称和参数在一行上,如果消息队列是空的,那么直接输出“EMPTY QUEUE!”,对于“PUT”指令,不需要输出什么;

Sample Input:

GET

PUT msg1 10 5

PUT msg2 10 4

GET

GET

GET

Sample Output:

EMPTY QUEUE!

msg2 10

msg1 10

EMPTY QUEUE!

解题思路:

本题是模拟Windows处理消息队列,很有意义,解题中主要遇到的问题是超时错误,根据本题的特点,宜使用优先队列容器来实现;

另外,光是用优先队列容器还不行,必须采用scanf和printf输入输出,否则还会超时,因为本题的数据量大,多达60000行字符串需要处理,需要输入输出;

The Code Follows:

<span style="font-family:Microsoft YaHei;font-size:18px;">#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

struct Message {  //这里不要用typedef了,因为重载运算符参数类型Message不能识别;
char Name[200];
int data, priority;

bool operator < (const Message a) const  //重载 < 运算符自定义排序准则;
{
return a.priority < priority;
}
};

int main()
{
priority_queue <Message> v; //定义一个优先队列的对象;
char command[200];

while(~scanf("%s", command)) {  //输入命令;
Message message;
if(strcmp(command, "GET") == 0) {
if(v.size() == 0) {      //队列为空;
printf("EMPTY QUEUE!\n");  //使用cout<<"EMPTY QUEUE"<<endl;不会超时;
}else {
printf("%s %d\n", v.top().Name, v.top().data); //使用cout<<v.top().Name<<v.top().data会超时;
v.pop();    //出队列操作,即将当前消息清除;
}
}else if(strcmp(command, "PUT") == 0) {
scanf("%s %d %d", message.Name, &message.data, &message.priority);
v.push(message);   //入列;
}
}
return 0;
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息