C++(14)STL分析与实践之容器适配器
来源:互联网 发布:linux wexitstatus 编辑:程序博客网 时间:2024/05/22 05:07
STL实践与分析
--容器适配器
引:
除了顺序容器,标准库还提供了三种顺序容器适配器:queue,priority_queue和stack,适配器是标准库中的概念,包括容器适配器,迭代器适配器和函数适配器。
适配器通用的操作和类型
size_type
一种类型,足以存储此适配器类型的最大对象长度
value_type
0
container_type
基础容器类型,适配器在此容器类型上实现
Aa;
创建一个空适配器,命名为a
Aa(c);
创建一个名为a的新适配器,初始化为c的副本
关系操作符
所有的适配器都支持全部关系操作符:==,!=,<,<=,>,>=
1、使用适配器时,必须包含相关头文件:
- #include <stack>
- #include <queue>
2、覆盖基础容器类型
默认的queue和stack都是基于deque实现,而priority_queue则再vector容器上实现,在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型实参,可覆盖其关联的基础容器类型:
- 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)
再栈顶压入元素
- 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提供的操作来实现栈功能。例如,执行下面的语句:
- 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允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
- //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();
- }
- }
- //习题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容器则更适用于需要存储(乃至修改)每个键所关联的值的情况。
set和map类型的对象不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用multimap或multiset,这两种类型允许多个元素拥有相同的键。
一、pair类型
pair类型在utility头文件中定义:
- #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的(公有)数据成员
1、pair的创建和初始化
在创建pair对象时,必须提供两个类型名:pair对象所包含的两个数据成员各自对应的类型名,这两个类型不必相同:
- pair<string,string> anon;
- pair<string,int> word_count;
- pair<string,vector<int> > line;
可以在定义时为每个成员提供初始化式:
- pair<string,string> author("James","Joyce");
- cout << "First: " << author.first << endl;
- cout << "Second: " << author.second << endl;
可以利用typedef简化pair的声明:
- typedef pair<string,string> Author;
- Author proust("Marcel","Proust");
- Author joyce("James","Joyce");
2、pair对象的操作
与其他标准库类型不同:对于pair类,可以直接访问其数据成员,因为其数据成员都是公有的,分别命名为first和second:
- 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对象:
- pair<string,string> next_auth;
- string first,last;
- while (cin >> first >> last)
- {
- next_auth = make_pair(first,last);
- }
等价于:
- //利用构造函数
- next_auth = pair<string,string>(first,last);
由于pair的数据成员是公有的,所以可以直接的读取输入:
- pair<string,string> next_auth;
- while (cin >> next_auth.first >> next_auth.second)
- {
- //...
- }
- //P308 习题10.1
- vector< pair<string,int> > paiVec;
- pair<string,int> paiVal;
- while (cin >> paiVal.first >> paiVal.second)
- {
- paiVec.push_back(paiVal);
- }
- //习题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);
- }
- //2
- vector< pair<string,int> > paiVec;
- string first;
- int second;
- while (cin >> first >> second)
- {
- paiVec.push_back(make_pair(first,second));
- }
- //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++(14)STL分析与实践之容器适配器
- C++(12)STL实践与分析之顺序容器
- C++(15)STL实践与分析之Map类型
- C++(16)STL实践与分析之初探算法
- C++(17)STL实践与分析之再谈迭代器
- STL 之容器适配器
- STL之容器适配器
- c++STL(五)容器适配器
- 初探STL之容器适配器
- c++STL之顺序容器(vector、deque、list)分析
- C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器
- C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器
- C++(13)STL实践与分析之再谈String类型
- C++之STL(十一):容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例
- 【C++】STL常用容器总结之六:基于deque的顺序容器适配器
- STL中的顺序性容器、关联性容器与容器适配器
- STL之容器适配器:stack,queue , priority_queue
- 从零开始学C++之STL(十一):容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例
- 【CF245H】【Queries for Number of Palindromes】
- android 设置全屏,窗口透明度,待机设置,主题设置总结
- Objective-C文章中的生词
- hdu 5340 Three Palindromes
- POJ-2242 The Circumference of the Circle-已知三点共圆求周长
- C++(14)STL分析与实践之容器适配器
- Codeforces Round #274 (Div. 2)E. Riding in a Lift
- JS闭包与内存泄漏
- 在数组中需找连续“1”的起始位置和结束位置
- POJ-2739 Sum of Consecutive Prime Numbers-求一个数满足有多少组递增相加的素数等于该数
- ACdream1734 Can you make a water problem?(贪心)
- iOS8的UITextView问题
- HDU-1686-Oulipo
- POJ 2752 Seek the Name, Seek the Fame