STL实践与分析
--容器适配器
引:
除了顺序容器,标准库还提供了三种顺序容器适配器:queue,priority_queue和stack,适配器是标准库中的概念,包括容器适配器,迭代器适配器和函数适配器。
适配器通用的操作和类型 |
size_type |
一种类型,足以存储此适配器类型的最大对象长度 |
value_type |
0 |
container_type |
基础容器类型,适配器在此容器类型上实现 |
Aa; |
创建一个空适配器,命名为a |
Aa(c); |
创建一个名为a的新适配器,初始化为c的副本 |
关系操作符 |
所有的适配器都支持全部关系操作符:==,!=,<,<=,>,>= |
1、使用适配器时,必须包含相关头文件:
[cpp] view plain copy print ?
- #include <stack>
- #include <queue>
#include <stack>
#include <queue>
2、覆盖基础容器类型
默认的queue和stack都是基于deque实现,而priority_queue则再vector容器上实现,在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可覆盖其关联的基础容器类型:
[cpp] view plain copy print ?
- stack<string> strStk;
- stack< string,vector<string> > str_stk;
- stack< string,vector<string> > str_stk2(strStk);
- stack< string,vector<string> > str_stk3(str_stk);
stack<string> strStk;
stack< string,vector<string> > str_stk;
stack< string,vector<string> > str_stk2(strStk); //Error
stack< string,vector<string> > str_stk3(str_stk); //OK
stack适配器所关联的基础容器可以是任意一种顺序容器类型。因此,stack栈可以建立在vector、list或者 deque容器之上。而queue适配器要求其关联的基础容器必须提供push_front运算,因此只能建立在list容器上,而不能建立在vector容器上。priority_queue适配器要求提供随机访问功能,因此可建立在vector或 deque容器上,但不能建立在list容器上。
3、适配器的关系运算由其中的元素依次比较来实现
一、栈适配器
栈容器适配器支持的操作 |
s.empty() |
如果栈为空,则返回true,否则返回false |
s.size() |
返回栈中元素的个数 |
s.pop() |
删除栈顶元素,但不返回其值 |
s.top() |
返回栈顶元素,但不删除该元素 |
s.push(item) |
再栈顶压入元素 |
[html] view plain copy print ?
- const stack<int>::size_type stk_size = 10;
- stack<int> intStk;
-
- int ix = 0;
- while (intStk.size() != stk_size)
- {
- intStk.push(ix ++);
- }
-
- int err_cnt = 0;
- while (!intStk.empty())
- {
- int val = intStk.top();
- if (val != --ix)
- {
- cerr << "oops! expected " << ix
- << " received " << val << endl;
- ++err_cnt;
- }
- intStk.pop();
- }
-
- cout << "Our Program ran with " << err_cnt << " errors!" << endl;
const stack<int>::size_type stk_size = 10;
stack<int> intStk;
int ix = 0;
while (intStk.size() != stk_size)
{
intStk.push(ix ++);
}
int err_cnt = 0;
while (!intStk.empty())
{
int val = intStk.top();
if (val != --ix)
{
cerr << "oops! expected " << ix
<< " received " << val << endl;
++err_cnt;
}
intStk.pop();
}
cout << "Our Program ran with " << err_cnt << " errors!" << endl;
默认情况下,栈适配器建立在deque容器上,因此采用deque提供的操作来实现栈功能。例如,执行下面的语句:
[html] view plain copy print ?
- intStack.push(ix++);
intStack.push(ix++);
这个操作通过调用push_back操作实现,而该intStk所基于的 deque对象提供。尽管栈是以deque容器为基础实现的,但是程序员不能直接访问deque所提供的操作。
二、队列和优先级队列
使用这两种队列,必须包含queue头文件。
队列和优先级队列支持的操作 |
q.empty() |
如果队列为空,则返回true,否则返回false |
q.size() |
返回队列中元素的个数 |
q.pop() |
删除队首元素,但不返回其值 |
q.front() |
返回队首元素,但不删除该元素 该操作只适用于队列 |
q.back() |
返回对尾元素,但不删除该元素 该操作只适用于队列 |
q.top() |
返回具有最高优先级的元素值,但不删除该元素 该操作只适用于优先级队列 |
q.push(item) |
对于queue,在队尾插入一个新的元素, 对于priority_queue,在基于优先级的适当位置插入新元素 |
priority_queue允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
[html] view plain copy print ?
- //P302 习题9.42
- int main()
- {
- // freopen("input","r",stdin);
- stack<string> strStk;
- string val;
-
- while (cin >> val)
- {
- strStk.push(val);
- }
-
- while (!strStk.empty())
- {
- val = strStk.top();
- cout << val << endl;
- strStk.pop();
- }
- }
//P302 习题9.42
int main()
{
// freopen("input","r",stdin);
stack<string> strStk;
string val;
while (cin >> val)
{
strStk.push(val);
}
while (!strStk.empty())
{
val = strStk.top();
cout << val << endl;
strStk.pop();
}
}
[cpp] view plain copy print ?
-
- int main()
- {
- freopen("input","r",stdin);
- stack<char> sexp;
- string exp;
- cin >> exp;
-
- string::iterator iter = exp.begin();
- while (iter != exp.end())
- {
- if (*iter != ')')
- {
- sexp.push(*iter);
- }
- else
- {
- while (!sexp.empty() && sexp.top() != '(')
- {
- cout << sexp.top() << endl;
- sexp.pop();
- }
- if (sexp.top() == '(')
- {
- sexp.pop();
- sexp.push('@');
- }
- else
- {
- cerr << "No match ( !" << endl;
- return 0;
- }
- }
- ++iter;
- }
-
- while (!sexp.empty())
- {
- cout << sexp.top() << endl;
- sexp.pop();
- }
- }