C++(14)STL分析与实践之容器适配器
2015-08-07 19:28
525 查看
STL实践与分析
--容器适配器引:
除了顺序容器,标准库还提供了三种顺序容器适配器:queue,priority_queue和stack,适配器是标准库中的概念,包括容器适配器,迭代器适配器和函数适配器。
适配器通用的操作和类型 | |
---|---|
size_type | 一种类型,足以存储此适配器类型的最大对象长度 |
value_type | 0 |
container_type | 基础容器类型,适配器在此容器类型上实现 |
Aa; | 创建一个空适配器,命名为a |
Aa(c); | 创建一个名为a的新适配器,初始化为c的副本 |
关系操作符 | 所有的适配器都支持全部关系操作符:==,!=,<,<=,>,>= |
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
#include <stack>
#include <queue>
2、覆盖基础容器类型
默认的queue和stack都是基于deque实现,而priority_queue则再vector容器上实现,在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可覆盖其关联的基础容器类型:
[cpp] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
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) | 再栈顶压入元素 |
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
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
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
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,在基于优先级的适当位置插入新元素 |
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//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
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//习题9.43
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();
}
}
STL实践与分析
--引言、pair类型、关联容器
引言:关联容器与顺序容器的本质区别在于:关联容器通过键[key]来存储和读取元素,而顺序容器则通过元素在容器中的位置顺序的存取元素。
map的元素以键-值【key-value】对的形式组织:键用作元素在map中的索引,而值则表示所存储和读取的数据。
set仅包含一个键,并有效的支持关于某个键是否存在的查询。
关联容器类型 | |
---|---|
map | 关联数组:元素通过键来存取 |
Set | 大小可变的集合,支持通过键来实现的快速读取 |
multimap | 支持同一个键多次出现的map类型 |
multiset | 支持同一个键多次出现的set类型 |
set和map类型的对象不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用multimap或multiset,这两种类型允许多个元素拥有相同的键。
一、pair类型
pair类型在utility头文件中定义:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
#include <utility>
pair类型提供的操作 | |
---|---|
pair<T1,T2>p1 | 创建一个空的pair对象,他的两个元素分别是T1和T2类型,采用值初始化 |
pair<T1,T2>p1(v1,v2) | 创建一个pair对象,它的两个元素分别是T1和T2,其中first成员初始化为v1,而second成员初始化为v2 |
make_pair(v1,v2) | 以v1和v2值创建一个新的pair对象,其元素类型分别为v1和v2的类型 |
p1< p2 | 两个pair对象之间的小于运算,其定义遵循字典次序:如果p1.first< p2.first 或者!(p2.first< p1.first) && p1.second < p2.second,则返回true |
p1== p2 | 如果两个pair对象的first和second成员依次相等,则这两个对象相等。该运算使用其元素的==操作符 |
p.first | 返回p中名为first的(公有)数据成员 |
p.second | 返回p的名为second的(公有)数据成员 |
在创建pair对象时,必须提供两个类型名:pair对象所包含的两个数据成员各自对应的类型名,这两个类型不必相同:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
pair<string,string> anon;
pair<string,int> word_count;
pair<string,vector<int> > line;
可以在定义时为每个成员提供初始化式:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
pair<string,string> author("James","Joyce");
cout << "First: " << author.first << endl;
cout << "Second: " << author.second << endl;
可以利用typedef简化pair的声明:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
typedef pair<string,string> Author;
Author proust("Marcel","Proust");
Author joyce("James","Joyce");
2、pair对象的操作
与其他标准库类型不同:对于pair类,可以直接访问其数据成员,因为其数据成员都是公有的,分别命名为first和second:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
typedef pair<string,string> Author;
Author author("James","Joyce");
string firstBook;
if (author.first == "James" && author.second == "Joyce")
{
firstBook = "Stephen Hero";
}
3、生成新的pair对象
出了构造函数,标准库还定义了make_pair函数,又传递给它的两个实参生成一个新的pair对象:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
pair<string,string> next_auth;
string first,last;
while (cin >> first >> last)
{
next_auth = make_pair(first,last);
}
等价于:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//利用构造函数
next_auth = pair<string,string>(first,last);
由于pair的数据成员是公有的,所以可以直接的读取输入:
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
pair<string,string> next_auth;
while (cin >> next_auth.first >> next_auth.second)
{
//...
}
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//P308 习题10.1
vector< pair<string,int> > paiVec;
pair<string,int> paiVal;
while (cin >> paiVal.first >> paiVal.second)
{
paiVec.push_back(paiVal);
}
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//习题10.2
//(1)
typedef pair<string,int> str_int;
vector< str_int > paiVec;
str_int paiVal;
while (cin >> paiVal.first >> paiVal.second)
{
paiVec.push_back(paiVal);
}
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//2
vector< pair<string,int> > paiVec;
string first;
int second;
while (cin >> first >> second)
{
paiVec.push_back(make_pair(first,second));
}
[html] view
plaincopy
![](https://code.csdn.net/assets/CODE_ico.png)
//3
vector< pair<string,int> > paiVec;
string first;
int second;
while (cin >> first >> second)
{
paiVec.push_back(pair<string,int>(first,second));
}
二、关联容器
1、关联容器共享大部分– 但并不是所有的顺序容器的操作:关联容器不支持front、push_front、pop_front、back、pop_back操作。
2、顺序容器和关联容器公共的操作有一下几种:
1)表9.2描述的前三种构造函数:
2)关联容器不能通过容器大小来定义,因为这样的话就无法知道键所对应的值是什么。
3)第9.3.4节中描述的关系运算。
4)表9.6列出的begin、end、rbegin和 rend操作。
5)表9.5列出的类型别名(typedef)。注意,对于map容器,value_type并非元素的类型,而是描述键及其关联值类型的pair类型。
6)表9.11中描述的 swap和赋值操作。但关联容器不提供assign函数。
7)表9.10列出的 clear和 erase操作,但关联容器的erase运算返回 void类型。
8)表9.8列出的关于容器大小的操作。但resize函数不能用于关联容器。
3、根据键排列元素
除了上述列出的操作之外,关联容器还提供了其他的操作。而对于顺序容器也提供的相同操作,关联容器也重新定义了这些操作的含义或返回类型,其中的差别在于关联容器中使用了键。
“容器元素根据键的次序排列”:在迭代关联容器时,我们可以确保按照键的顺序访问元素,而与元素在容器中的位置完全无关!
本文借鉴:http://blog.csdn.net/column/details/zjf666.html?&page=4
相关文章推荐
- C++(13)STL实践与分析之再谈String类型
- C++(12)STL实践与分析之顺序容器
- C++(11)标准I/O库
- C++(10)函数
- C++(9)语句
- C语言枚举的用法
- C++(8)表达式
- C++(7)动态数组
- C++(6)C风格字符串
- [C/C++标准库]_[初级]_[std::vector的多线程读写问题]
- [C/C++标准库]_[初级]_[std::vector的多线程读写问题]
- C++(5)指针
- C++(4)数组
- C++(3)标准库类型
- eclipse报错lib32stdc++6
- C++(2)基本数据类型
- C++(1)入门
- 链表实现队列 c语言
- 一致性hash算法 C++语言实现
- [C++11 并发编程] 03 - 向线程传递参数