• <STL学习笔记>Priority_queue


      优先队列是一种容器适配器(容器适配器的概念本人不会解释,故此处无法作出说明),它的第一个元素(位于头部top)总是队列中最大的元素,这里的“最大”是指队列元素的严格弱序中的“最大”。严格弱序是一系列数或事物按照一定的比较关系“<”排列得出的序列,“<”可以是数学中进行数值比较的大于,也可以是小于,还可以是其它含义,这大概与离散数学中的“偏序关系”相仿。

        在内存充足的情况下,优先队列能被无限地插入元素。

        优先队列作为一个容器适配器,它使用其它容器作为底层容器,并提供一系列访问元素的函数。优先队列中的元素从底层容器的“尾部(back)”弹出,即是从队列的顶部(top)弹出。底层容器需要满足的条件是可以通过迭代器随机访问其中的元素并且支持以下的操作:

    • front()
    • push_back()
    • pop_back()

    故此,容器vector和deque可以作为底层容器,在创建优先队列时若没有声明使用何种容器,则默认使用vector。

    创建一个优先队列的格式:

    priority_queue<T, Container, Compare>

        可以看出,创建一个优先队列默认需要三个参数(实际应用上有些参数可以省去)。参数解释:

       T队列中元素的数据类型

       Container: 用于储存和访问队列元素的底层容器的类型。

       Compare: 比较关系,默认是数值上的小于关系,比如1<2,6<7,此时队列中元素由队头到队由大到小排列,采用默认compare时此参数可以省去。当需要采用其它标准进行比较时需要额外定义这一比较方式(下例示)。当满足比较关系”<”时,返回true,否则返回false。

      创建优先队列的一个例子:

    View Code
     1 #include <iostream>
     2 #include <queue>
     3 using namespace std;
     4 
     5 class cmp
     6 {
     7 public:
     8    bool operator() (const int a,const int b)
     9    {
    10        return a>b;
    11    }
    12 };
    13 
    14 int main()
    15 {
    16     priority_queue<int,vector<int>,cmp>que1;
    17     priority_queue<int,vector<int> >que2;
    18     int a[]={1,3,4,2,5,0,6};
    19     for(int i=0;i<7;i++)
    20     {
    21         que1.push(a[i]);
    22         que2.push(a[i]);
    23 }
    24     cout<<"que1:";
    25     while(!que1.empty())
    26     {
    27         cout<<que1.top()<<" ";
    28         que1.pop();
    29     }
    30     cout<<endl<<"que2:";
    31     while(!que2.empty())
    32     {
    33         cout<<que2.top()<<" ";
    34         que2.pop();
    35     }
    36     return 0;
    37 }

      输出结果:

    que1:0 1 2 3 4 5 6

    que2:6 5 4 3 2 1 0

      上例中que1使用比较方式cmp类,队列中元素由小到大排列,而que2使用默认形式的“<”,元素按照优先级排列,队头元素最大。

      优先队列成员函数(除构造函数、析构函数)简介:

    (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

    给队列插入元素,新元素会按其优先级被排列到适当位置。

    注:对于自定义类型比如结构体,必须重载<才能进行比较。见下例:

    View Code
     1 #include <iostream>
     2 #include <queue>
     3 using namespace std;
     4 
     5 class Node
     6 {
     7 public:
     8     int idx;
     9     static int cnt;
    10     Node()
    11     {
    12         idx=cnt++;
    13     }
    14 }a[10];
    15 
    16 int Node::cnt=1;
    17 
    18 bool operator < (Node a,Node b)
    19 {
    20     return a.idx>b.idx;
    21 }
    22 
    23 int main()
    24 {
    25 //省略container和compare参数,此时container默认使用vector,而compare默认使用<,而<已经重载,于是可以按照自定义方式比较。
    26     priority_queue<Node>que;//省略container和compare参数
    27     for(int i=0;i<10;i++)
    28         que.push(a[i]);
    29     while(!que.empty())
    30     {
    31         cout<<que.top().idx<<" ";
    32         que.pop();
    33     }
    34     return 0;
    35 }

    结果:1 2 3 4 5 6 7 8 9 10 

      若将上述重载<函数中的return a.idx>b.idx;改为return a.idx<b.idx;则输出:10 9 8 7 6 5 4 3 2 1

    可以看出,利用自定义compare可以使得优先队列按照某些所需要的规则排序。

  • 相关阅读:
    NodeJs学习历程
    MongoDb学习历程
    递归函数为什么要防止栈溢出
    *args 是可变参数,args 接收的是一个 tuple; **kw 是关键字参数,kw 接收的是一个 dict。
    list和tuple的区别
    python源码阅读
    常用的线程池有哪些?
    备份
    假设你正在爬楼梯,需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶,你有多少种不同的方法可以爬到楼顶呢?
    最后一个单词的长度
  • 原文地址:https://www.cnblogs.com/cszlg/p/2611607.html
Copyright © 2020-2023  润新知