ACM/ICPC竞赛
第07篇 ACM/ICPC竞赛之STL--stack/queue
stack(栈)和queue(队列)也是在程序设计中经常会用到的数据容器,STL为我们提供了方便的stack(栈)的queue(队列)的实现。
准确地说,STL中的stack和queue不同于vector、list等容器,而是对这些容器的重新包装。这里我们不去深入讨论STL的stack和queue的实现细节,而是来了解一些他们的基本使用。
1、stack
stack模板类的定义在<stack>头文件中。
stack模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型为deque。
定义stack对象的示例代码如下:
stack<int> s1;
stack<string> s2;
stack的基本操作有:
入栈,如例:s.push(x);
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()
下面是用string和stack写的解题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 }
2、queue
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()
3、priority_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时,最困难的可能就是如何定义比较算子了。
如果是基本数据类型,或已定义了比较运算符的类,可以直接用STL的less算子和greater算子——默认为使用less算子,即小的往前排,大的先出队。
如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:重载比较运算符。优先队列试图将两个元素x和y代入比较运算符(对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
未完待续!!!