优先队列的基本使用及样例

来源:互联网 发布:番茄时间管理 知乎 编辑:程序博客网 时间:2024/06/05 01:06

STL 中栈的使用方法(stack)
头文件:

 #include <stack>

基本操作:
push(x) 将x加入栈中,即入栈操作

pop() 出栈操作(删除栈顶),只是出栈,没有返回值

top() 返回第一个元素(栈顶元素)

size() 返回栈中的元素个数

empty() 当栈为空时,返回 true

STL 中队列的使用(queue)
头文件:

#include <queue>

基本操作:
push(x) 将x压入队列的末端

pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回任何值

front() 返回第一个元素(队顶元素)

back() 返回最后被压入的元素(队尾元素)

empty() 当队列为空时,返回true

size() 返回队列的长度

———- 栈和队列的用法都相对简单,下面详细介绍优先队列的用法 ———–

STL 中优先队列的使用详细介绍(priority_queu)

#include <queue>

基本操作:
empty() 如果队列为空返回真

pop() 删除对列首元素

push() 加入一个元素

size() 返回优先队列中拥有的元素个数

top() 返回优先队列首元素

在默认的优先队列中,优先级高的先出队。

标准库默认使用元素类型的 < 操作符来确定它们之间的优先级关系。

(1)优先队列的第一种用法,这是最常用的默认的优先级用法,也就是优先级高的先出队列,例如说一个int优先队列,那么出队的时候就是int大的先出队列。

下面给出一个例子:

#include <iostream>  #include <queue>  using namespace std;  int main()  {      priority_queue<int> q;      for(int i = 1;i <= 5;i++)      {          q.push(i);      }      for(int i = 0;i < 5;i++)      {          cout<<q.top()<<endl;          q.pop();      }      return 0;  }  

运行结果可想而知,就是从大到小的: 5 4 3 2 1

(2).那么如果想要优先队列中低优先级的元素先出队列,怎么办呢? — 自定义优先级

①方法一:我们可以传入一个比较函数,使用functional头文件中的greater函数对象作为比较函数

注意:首先要添加头文件:#include

priority_queue< int,vector,greater > q; // 注意:> > 误写成>> 会报错(中间有空格)

这样我们就创建了一个低优先级元素先出对列的优先队列。

修改上面的例子,运行,就会发现,输出的顺序变成了:1 2 3 4 5。

当然,与greater相对的less,如果传入less这个比较函数,那么就是高优先级元素先出队列了。

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

以上创建的优先队列是相同的。

②方法二:自己实现比较函数

struct cmp1  {      bool operator ()(int x,int y)      {          return x>y; //小值优先      }  };  priority_queue<int,vector<int>,cmp1 > q;

这样就创建了一个小值元素先出队列的优先队列,这里的 cmp1 作用就相当于 greater
同理我们可以写出:

struct cmp2  {      bool operator ()(int x,int y)      {          return x<y; //大值优先      }  };  priority_queue<int,vector<int>,cmp2 > q;

这里就是创建了一个大值元素先出队列的优先队列,这里的 cmp2 作用也就是相当于 less

(3)假如优先队列中的元素是一个结构对象或者是类对象,那么如何重新自定义其优先级比较呢?

例子一:定义一个结构体,这个结构体只有一个元素 x 。

①低优先级元素先出队列,也就是x值小的先出队列。

struct number1  {      int x;      bool operator < (const number1 &a) const      {          return x>a.x;//小值优先      }  };  number1 num1[5];      priority_queue<number1>q;      for(int i = 1; i <= 5; i++)      {          num1[i].x = i;          q.push(num1[i]);      }      for(int i = 1; i <= 5; i++)      {          cout<<q.top().x<<endl;          q.pop();      }  输出: 1 2 3 4 5

②高优先级元素先出队列,也就是x值大的先出队列。

struct number2  {      int x;      bool operator < (const number2 &a) const      {          return x<a.x;//大值优先      }  };  

注意到:结构体中重载的运算符只可以是 <, 因为标准库默认使用元素类型的 < 操作符来确定它们之间的优先级关系,如果重载 > ,那么会编译错误。

例子二:在上面的例子中,我们是将 结构体中的 x 的大小当做是优先级比较值了。下面给出另一例子,这个例子更具有一般性。

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

在这个结构体中,priority表征优先级值。

priority_queue<node> qn;      node b[5];      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(int i = 0; i < 5; i++)          qn.push(b[i]);      cout<<"优先级"<<'\t'<<"值"<<endl;      for(int i = 0; i < 5; i++)      {          cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;          qn.pop();      }  输出结果为:优先级  值9          58          26          12          31          46

结构体:

class  node   {   public :        int  a;      node(){}       node( int  x):a(x){}   friend   bool  operator<( const  node ne1, const  node ne2)//参数也可以为引用,值传递       {            if (ne1.a > ne2.a)           {                return   true ;           }            else           {                return   false ;           }       }   };   

优先队列及各种排序自定义函数
优先队列:
一般元素类型:

priosity_queue<int>Q;(默认大顶堆)priosity_queue<int,vector<int>,greater<int>>Q;(小顶堆)

结构体元素类型:

struct node{   int x,y,z;   friend bool operator <(const node &a,const node &b)   {      return a.x>b.x;(小顶)     ///return a.x<b.x;(大顶)   }};priosity_queue<node>Q;

特殊要求类型:

struct  cmp{   bool operator ()(const int &a,const int &b)   {      return abs(a-3)>abs(b-3);(小顶)(反之大顶)   }};priosity_queue<int,vector<int>,cmp>Q;

指针优先队列:(转载,表不懂)
其中在c++primer第三版 中文版中关于操作符重载有如下描述:
“程序员只能为类类型或枚举类型的操作数定义重载操作符我们可以这样来实现把重
载操作符声明为类的成员或者声明为名字空间成员同时至少有一个类或枚举类型的参数
按值传递或按引用传递”
因此不可用指针类型的参数;
2、如果想定义一个指针类型的优先队列,那就不可这么简单的定义了,你需要自定义一个自己的比较函数,在priority_queue的模板函数中,我们可以利用这样一个template

class  nodePointerComparer  {  public :      nodePointerComparer(){}       bool  operator ()( const  node* ne1,  const  node* ne2)  const       {           return  ne1->lessthan(ne2);      }  };  

当然在这之前我们的类Node要重新书写

class  node  {  public :       int  a;      node(){}      node( int  x):a(x){}      bool  lessthan( const  node* pnode)  const       {           return  a < pnode->a;      }  };  

这样在main函数中就可以定义指针类型的优先队列了:

int  main()  {      priority_queue <node*, vector <node*>, nodePointerComparer> qn;      node *n1 =  new  node(90);      node *n2 =  new  node(2);      node *n3 =  new  node(50);     qn.push(n1);      qn.push(n2); /span>>     qn.push(n3);      int  size = qn.size();       for ( int  i = 0; i < size; i++)      {          cout << qn.top()->a << endl;          qn.pop();      }       return  0; }  

疑问之处:如果你使用第一种值传递的操作符重载,来实现第二种的指针类型优先队列,是不会达到想要的结果的,个人理解是因为在指针类型的优先队列中找“<”运算符的时候,重载的不是我们写的值传递friend bool operator<(const node ne1,const node ne2)//
也就是没有找到指针类型的”<”重载,所有不会达到优先队列的效果。

原创粉丝点击