容器适配器
容器适配器
除了顺序容器,标准库还提供了三种顺序容器适配器:queue、priority_queue 和 stack。 适配器(adaptor) 是标准库中通用的概念,包括容器适配器、迭代器适配器和函数适配器。本质上,适配器是使一事物的行为类似于另一事物的行为的一种机制。
适配器通用的操作和类型
|
size_type |
一种类型,足以存储此适配器类型最大对象的长度 |
|
value_type |
元素类型 |
|
container_type |
基础容器的类型,适配器在此容器类型上实现 |
|
A a; |
创建一个新空适配器,命名为 a |
|
A a(c); |
创建一个名为 a 的新适配器,初始化为容器 c 的副本 |
|
关系操作符 |
所有适配器都支持全部关系操作符:==、 !=、 <、 <=、 >、>= |
使用适配器时,必须包含相关的头文件:
#include <stack> // stack adaptor
#include <queue> // both queue and priority_queue adaptors
适配器的初始化
所有适配器都定义了两个构造函数:默认构造函数用于创建空对象,而带一个容器参数的构造函数将参数容器的副本作为其基础值。例如,假设 deq 是deque<int> 类型的容器,则可用 deq 初始化一个新的栈,如下所示:
stack<int> stk(deq); // copies elements from deq into stk
覆盖基础容器类型默认的 stack 和 queue 都基于 deque 容器实现,而 priority_queue 则在 vector 容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可覆盖其关联的基础容器类型:
// empty stack implemented on top of vector
stack< string, vector<string> > str_stk;
// str_stk2 is implemented on top of vector and holds a copy of svec
stack<string, vector<string> > str_stk2(svec);
对于给定的适配器,其关联的容器必须满足一定的约束条件。stack 适配器所关联的基础容器可以是任意一种顺序容器类型。因此,stack 栈可以建立在vector、list 或者 deque 容器之上。而 queue 适配器要求其关联的基础容器必须提供 push_front 运算,因此只能建立在 list 容器上,而不能建立在vector 容器上。priority_queue 适配器要求提供随机访问功能,因此可建立在vector 或 deque 容器上,但不能建立在 list 容器上。
适配器的关系运算
两个相同类型的适配器可以做相等、不等、小于、大于、小于等于以及等于关系比较,只要基础元素类型支持等于和小于操作符既可。这些关系运算由元素依次比较来实现。第一对不相等的元素将决定两者之间的小于或大于关系。
栈适配器
栈容器适配器支持的操作
|
s.empty() |
如果栈为空,则返回 true,否则返回 stack |
|
s.size() |
返回栈中元素的个数 |
|
s.pop() |
删除栈顶元素的值,但不返回其值 |
|
s.top() |
返回栈顶元素的值,但不删除该元素 |
|
s.push(item) |
在栈顶压入新元素 |
// number of elements we'll put in our stack
const stack<int>::size_type stk_size = 10;
stack<int> intStack; // empty stack
// fill up the stack
int ix = 0;
while (intStack.size() != stk_size)
// use postfix increment; want to push old value onto intStack
intStack.push(ix++); // intStack holds 0...9 inclusive
int error_cnt = 0;
// look at each value and pop it off the stack
while (intStack.empty() == false) {
int value = intStack.top();
// read the top element of the stack
if (value != --ix) {
cerr << "oops! expected " << ix
<< " received " << value << endl;
++error_cnt; }
intStack.pop(); // pop the top element, and repeat
}
cout << "Our program ran with "
<< error_cnt << " errors!" << endl;
所有容器适配器都根据其基础容器类型所支持的操作来定义自己的操作。默认情况下,栈适配器建立在 deque 容器上,因此采用 deque 提供的操作来实现栈功能。
// use postfix increment; want to push old value onto intStack
intStack.push(ix++); // intStack holds 0...9 inclusive
这个操作通过调用 push_back 操作实现,而该 intStack 所基于的 deque对象提供。尽管栈是以 deque 容器为基础实现的,但是程序员不能直接访问deque 所提供的操作。例如,不能在栈上调用 push_back 函数,而是必须使用栈所提供的名为 push 的操作。
队列和优先级队列
标准库队列使用了先进先出(FIFO)的存储和检索策略。进入队列的对象被放置在尾部,下一个被取出的元素则取自队列的首部。标准库提供了两种风格的队列: FIFO 队列(FIFO queue, 简称 queue), 以及优先级队列(priority queue)。
priority_queue 允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。标准库默认使用元素类型的 < 操作符来确定它们之间的优先级关系。
要使用这两种队列,必须包含 queue 头文件。
队列和优先级队列支持的操作
|
q.empty() |
如果队列为空,则返回 true,否则返回 false |
|
q.size() |
返回队列中元素的个数 |
|
q.pop() |
删除队首元素,但不返回其值 |
|
q.front() |
返回队首元素的值,但不删除该元素该操作只适用于队列 |
|
q.back() |
返回队尾元素的值,但不删除该元素该操作只适用于队列 |
|
q.top() |
返回具有最高优先级的元素值,但不删除该元素该操作只适用于优先级队列 |
|
q.push(item) |
对于 queue,在队尾压入一个新元素,对于 priority_quue,在基于优先级的适当位置插入新元素 |

浙公网安备 33010602011771号