zoukankan      html  css  js  c++  java
  • ACM/ICPC竞赛

    07篇 ACM/ICPC竞赛之STL--stack/queue

    stack()queue(队列)也是在程序设计中经常会用到的数据容器,STL为我们提供了方便的stack()queue(队列)的实现。

    准确地说,STL中的stackqueue不同于vectorlist等容器,而是对这些容器的重新包装。这里我们不去深入讨论STLstackqueue的实现细节,而是来了解一些他们的基本使用。

    1stack

    stack模板类的定义在<stack>头文件中。

    stack模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型为deque

    定义stack对象的示例代码如下:

        stack<int> s1;

        stack<string> s2;

    stack的基本操作有:

        入栈,如例:s.push(x);

        出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。

        访问栈顶,如例:s.top()

        判断栈空,如例:s.empty(),当栈空时,返回true

        访问栈中的元素个数,如例:s.size()

    下面是用stringstack写的解题hduoj 1064--Parencoding的程序。

        

     1 #include <iostream>
     2 
     3     #include <string>
     4 
     5     #include <stack>
     6 
     7     using namespace std;
     8 
     9     main()
    10 
    11     {
    12 
    13         int n;
    14 
    15         cin >> n;
    16 
    17         for (int i=0; i<n; i++)
    18 
    19         {
    20 
    21             int m;
    22 
    23             cin >> m;
    24 
    25             string str;
    26 
    27             int leftpa = 0;
    28 
    29             for (int j=0; j<m; j++)  // 读入P编码,构造括号字符串
    30 
    31             {
    32 
    33                 int p;
    34 
    35                 cin >> p;
    36 
    37                 for (int k=0; k<p-leftpa; k++) str += '(';
    38 
    39                  str += ')';
    40 
    41                 leftpa = p;
    42 
    43             }
    44 
    45              stack<int> s;
    46 
    47             for ( string::iterator it=str.begin(); it!=str.end(); it++ )
    48 
    49             {   // 构造M编码
    50 
    51                 if (*it=='(')
    52 
    53                     s. push (1);
    54 
    55                 else
    56 
    57                 {
    58 
    59                     int p = s. top (); s. pop ();
    60 
    61                     cout << p << " ";
    62 
    63                     if (!s. empty ()) s. top () += p;
    64 
    65                 }
    66 
    67             }
    68 
    69             cout << endl;
    70 
    71         }
    72 
    73         return 1;
    74 
    75     }

    2queue

    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()

    3priority_queue

    <queue>头文件中,还定义了另一个非常有用的模板类 priority_queue(优先队列)。优先队列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。

    priority_queue模板类有三个模板参数,第一个是元素类型,第二个容器类型,第三个是比较算子。其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大的往后排(出队时序列尾的元素出队)。

    定义priority_queue对象的示例代码如下:

        priority_queue<int> q1;

        priority_queue< pair<int, int> > q2;  // 注意在两个尖括号之间一定要留空格。

        priority_queue<int, vector<int>, greater<int> > q3; // 定义小的先出队

    priority_queue的基本操作与queue相同。

    初学者在使用priority_queue时,最困难的可能就是如何定义比较算子了。

    如果是基本数据类型,或已定义了比较运算符的类,可以直接用STLless算子和greater算子——默认为使用less算子,即小的往前排,大的先出队。

    如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:重载比较运算符。优先队列试图将两个元素xy代入比较运算符(less算子,调用 x<y,对greater算子,调用x>y),若结果为真,则x排在y前面,y将先于x出队,反之,则将y排在x前面,x将先出队。

    看下面这个简单的示例:

        

     1 #include <iostream>
     2 
     3     #include <queue>
     4 
     5     using namespace std;
     6 
     7     class T
     8 
     9     {
    10 
    11     public:
    12 
    13         int x, y, z;
    14 
    15         T(int a, int b, int c):x(a), y(b), z(c)
    16 
    17         {
    18 
    19         }
    20 
    21     };
    22 
    23     bool operator < (const T &t1, const T &t2)
    24 
    25     {
    26 
    27         return t1.z < t2.z;  // 按照z的顺序来决定t1和t2的顺序
    28 
    29     }
    30 
    31     main()
    32 
    33     {
    34 
    35         priority_queue<T> q;
    36 
    37         q.push(T(4,4,3));
    38 
    39         q.push(T(2,2,5));
    40 
    41         q.push(T(1,5,4));
    42 
    43         q.push(T(3,3,6));
    44 
    45  
    46 
    47         while (!q.empty())
    48 
    49         {
    50 
    51             T t = q.top(); q.pop();
    52 
    53             cout << t.x << " " << t.y << " " << t.z << endl;
    54 
    55         }
    56 
    57         return 1;
    58 
    59     }
    60 
    61  
    62 
    63 输出结果为(注意是按照z的顺序从大到小出队的):
    64 
    65  
    66 
    67     3 3 6
    68 
    69     2 2 5
    70 
    71     1 5 4
    72 
    73     4 4 3
     1 再看一个按照z的顺序从小到大出队的例子:
     2 
     3  
     4 
     5     #include <iostream>
     6 
     7     #include <queue>
     8 
     9     using namespace std;
    10 
    11     class T
    12 
    13     {
    14 
    15         public:
    16 
    17         int x, y, z;
    18 
    19         T(int a, int b, int c):x(a), y(b), z(c)
    20 
    21         {
    22 
    23         }
    24 
    25     };
    26 
    27     bool operator > (const T &t1, const T &t2)
    28 
    29     {
    30 
    31         return t1.z > t2.z;
    32 
    33     }
    34 
    35     main()
    36 
    37     {
    38 
    39         priority_queue<T, vector<T>, greater<T> > q;
    40 
    41         q.push(T(4,4,3));
    42 
    43         q.push(T(2,2,5));
    44 
    45         q.push(T(1,5,4));
    46 
    47         q.push(T(3,3,6));
    48 
    49  
    50 
    51         while (!q.empty())
    52 
    53         {
    54 
    55             T t = q.top(); q.pop();
    56 
    57             cout << t.x << " " << t.y << " " << t.z << endl;
    58 
    59         }
    60 
    61         return 1;
    62 
    63     }
    64 
    65  
    66 
    67 输出结果为:
    68 
    69  
    70 
    71     4 4 3
    72 
    73     1 5 4
    74 
    75     2 2 5
    76 
    77     3 3 6

    如果我们把第一个例子中的比较运算符重载为:

       

    1  bool operator < (const T &t1, const T &t2)
    2 
    3     {
    4 
    5         return t1.z > t2.z;  // 按照z的顺序来决定t1和t2的顺序
    6 
    7     }

    则第一个例子的程序会得到和第二个例子的程序相同的输出结果。

    再回顾一下用优先队列实现的题hduoj 1067--Ugly Numbers的代码:

      

     1   #include <iostream>
     2 
     3     #include <queue>
     4 
     5     using namespace std;
     6 
     7     typedef pair<unsigned long int, int> node_type;
     8 
     9     main( int argc, char *argv[] )
    10 
    11     {
    12 
    13         unsigned long int result[1500];
    14 
    15         priority_queue< node_type, vector<node_type>, greater<node_type> > Q;
    16 
    17         Q.push( make_pair(1, 3) );
    18 
    19         for (int i=0; i<1500; i++)
    20 
    21         {
    22 
    23             node_type node = Q.top();
    24 
    25             Q.pop();
    26 
    27             switch(node.second)
    28 
    29             {
    30 
    31             case 3: Q.push( make_pair(node.first*2, 3) );
    32 
    33             case 2: Q.push( make_pair(node.first*3, 2) );
    34 
    35             case 1: Q.push( make_pair(node.first*5, 1) );
    36 
    37             }
    38 
    39             result[i] = node.first;
    40 
    41         }
    42 
    43         int n;
    44 
    45         cin >> n;
    46 
    47         while (n>0)
    48 
    49         {
    50 
    51             cout << result[n-1] << endl;
    52 
    53             cin >> n;
    54 
    55         }
    56 
    57         return 1;
    58 
    59     }
    60 
    61  

    未完待续!!!

     

     

     

  • 相关阅读:
    如今我这样编程,你呢?
    专注UI——是alert()打败了你!
    创业公司十分钟简单搭建GIT私有库
    小胖说事22-----iOS开发技巧之取消键盘响应和截屏功能
    C++运算符重载的妙用
    汽水瓶
    Android 应用按返回键异常退出的问题
    053第256题
    Activity、FragmentActivity和AppCompatActivity的区别
    Android中Activity和AppcompatActivity的区别(详细解析)
  • 原文地址:https://www.cnblogs.com/jeff-wgc/p/4480321.html
Copyright © 2011-2022 走看看