15.1 标准模板库(STL)
容器
序列容器、有序关联容器、无序关联容器、容器适配器
标准库容器类 | 功能 | 迭代器类型 |
---|---|---|
序列容器 | ||
array | 固定大小,可以直接访问任何元素 | 随机访问迭代器 |
deque | 双向队列,可以在前后快速插入、删除,直接访问 | 随机访问迭代器 |
forward_list | 单链表,在任意位置快速插入和删除 | 随机访问迭代器 |
list | 双向链表,任意位置快速插入和删除 | 双向迭代器 |
vector | 在最后进行插入和删除,直接访问 | 双向迭代器 |
有序关联容器(键按顺序保存) | ||
set | 快速查找,无重复元素 | 双向迭代器 |
multiset | 快速查找,无重复元素 | 双向迭代器 |
map | 一对一映射,快速查找,无重复 | 双向迭代器 |
multimap | 一对一映射,快速查找,有重复 | 双向迭代器 |
无序关联容器 | ||
`unordered_set | 同上,但是不会自动排序 | 双向迭代器 |
unordered_multiset | 同上 | 双向迭代器 |
unordered_map | 同上 | 双向迭代器 |
unordered_multimap | 同上 | 双向迭代器 |
容器适配器 | ||
stack | 栈,后进先出 | 不支持迭代器 |
queue | 队列,先进先出 | 不支持迭代器 |
priority_queue | 优先级最高的先出 | 不支持迭代器 |
近容器
内置数组、标志位
bitset
、高速向量运算valarray
近容器类似于集合,可有对集合内的元素集体操作。功能与首类容器相似,但不支持所有功能
STL容器的通用函数
-
默认、拷贝、转移构造函数以及析构函数
-
empty;insert;size;clear
用于判空、插入、获得大小、清空容器 -
copy operator=;move operator=;operator<;operator<=;operator>;operator>=;operator==;false operator!=;
-
swap
交换两个容器中的元素,只适用于首类容器 -
max_size
返回一个容器的最大存储元素个数 -
begin
返回引用容器中第一个元素的iterator
或const_iterator
-
end
返回引用容器中最后一个元素之后位置的iterator
或const_iterator
-
cbegin
返回引用容器的第一个元素的const_iterator
-
cend
返回引用容器末端之后位置的const_iterator
-
rbegin
返回引用容器末端位置的reverse_iterator
或const_reverse_iterator
-
rend
返回引用容器第一个元素之前位置的reverse_iterator
或const_reverse_iterator
-
crbegin
返回引用容器末端的const_reverse_iterator
-
crend
返回引用容器第一个元素之前位置的const_reverse_iterator
-
erase
删除容器中的一个或者多个元素
迭代器
迭代器输入、输出
istream_iterator
:可以从标准输入cin
对象以类型安全的方式输入
ostream_iterator
:可以从标准输出cout
对象以类型安全的方式输出
int main(){ istream_iterator<int> inputInt(cin); int number1 = *inputInt; ++inputInt; int number2 = *inputInt; ostream_iterator<int> outputInt(cout); outputInt = number1+number2; }
Result:Enter two integers:
12 25The sum is
37
迭代器的类型
类型 | 功能 | 支持操作 |
---|---|---|
随机访问迭代器 | 可向前向后跳转任意个元素,直接访问容器中任何元素 | +=;-=;[];<;<=;>;>= |
双向迭代器 | 支持向前、向后移动 | p--;--p |
前向迭代器 | 综合输入、输出迭代器的功能 | |
输出迭代器 | 将元素写入容器,一次向前移动一个元素 | *p; |
输入迭代器 | 从容器中读取数据,一次向前移动一个元素 | *p;p->m;!= |
15.2 序列容器
array;vector;deque;list;forward_list
数组、动态数组、双向队列、双向链表、单链表
序列容器vector
vector
可以方便地在末端进行删除、插入操作:当容器内存空间耗尽时,会分配一个更大的内存空间,将原先数据赋值到新的空间,并将原空间释放,适合随时随机存储
成员函数
int main(){ const size_t SIZE=6; int values[SIZE] = {1, 2, 3, 4, 5, 6}; vector<int> integers; }
成员函数size
integers.size()
:返回当前容器所存储的元素数
成员函数capacity
integers.capacity()
:返回为容纳更多元素调整空间前可以存储的元素数
成员函数push_back;push_front
integers.push_back()
:在容器末端插入一个元素
integers.push_front()
:在容器首端插入一个元素
成员函数front;back
integers.front()
返回第一个元素的引用,而不像begin
返回的是迭代器
integers.back()
返回最后一个元素的引用
成员函数insert
integers.insert(integers.cbegin()+1, 22);//在第二个元素之前插入元素22 integers.insert(integers.cbegin(), values.cbegin(), values.cend());//在第一个元素之前插入数组values的值
两个参数的insert
:
-
第一个参数表示将要插入的位置,会将指定元素插入到该位置之前
-
第二个参数表示将要插入的元素的值
三个参数的insert
:
-
第一个参数表示将要插入之后的位置
-
第二、三参数共同表示将要插入一定范围的元素
成员函数erase
integers.erase(integers.cbegin()); integers.erase(integers.cbegin(), integers.cend());
一个参数的erase
:
-
一个参数指向将要删除位置的迭代器
两个参数的erase
:
-
第一个参数表示指向将要删除位置的起始迭代器
-
第二个参数表示删除元素的结束迭代器
一个参数时基于单个元素删除,两个参数是基于范围删除
成员函数clear
integers.clear()
:清空vector
容器中的所有元素
算法
ostream_iterator<int> output(cout, " "); copy(integers.cbegin(), integers.cend(), output);
ostream_iterator
输出迭代器的两个参数:
-
第一个参数指定输出流
-
第二个参数指定输出值之间的分隔符
copy
算法的三个参数:
-
第一个为开始迭代器
-
第二个为结尾迭代器
-
第三个是调用的输出迭代器输出值
开始迭代器通过自增最终应当等于结尾迭代器,二者构成一个输出范围
使用迭代器输出容器中的元素
使用前向迭代器
for(auto constIterator = integers.cbegin(); constIterator != integers.cend(); ++constIterator) cout<<*constIterator<<" ";
cbegin
返回第一个元素的迭代器,一直前进到末端最后一个位置结束
使用反向迭代器
for(auto constReverseIterator = integers.crbegin(); constReverseIterator != integers.crend(); ++constReverseIterator) cout<<*constReverseIterator<<" ";
crbegin
返回最后一个元素的迭代器,一直反向前进到第一个元素前一个位置结束
使用基于范围的for循环语句
for(auto const &item: integers) cout<<item<<" ";
序列容器list
声明
#include<list> using namespace std; int main(){ const size_t SIZE = 6; array<int, SIZE> ints = {2, 6, 4, 8}; list<int> values; list<int> otherValues; }
成员函数
成员函数push_front;push_back
成员函数sort
values.sort()
:对list
容器中的元素进行升序排序
成员函数splice
values.splice(values.cend(), otherValues);
:
-
第一个参数表示需要插入位置之前的位置迭代器
-
第二个参数表是插入的元素,在插入之后会将第二个参数容器中的元素删除
成员函数merge
values.merge(otherValues)
:将排序好的otherValues
容器元素按照values
容器中的顺序插入
成员函数pop_front;pop_back
pop_front
:删除容器中的第一个元素
pop_back
:删除容器中的最后一个元素
成员函数unique
values.unique()
:删除容器values
中的重复元素
注意:去重前需要将容器进行排序
成员函数swap
values.swap(otherValues)
:用于交换两个容器之间的元素
成员函数assin
values.assin(otherValues.cbegin(), otherValues.cend());
:用两个迭代器参数指定的一个范围元素取代原有的内容
成员函数remove
values.remove(4)
:删除容器中值为4的所有元素
序列容器deque
性能
在容器中间进行插入、删除操作:vector
<deque
<list
成员函数
成员函数push_front;push_back
成员函数pop_front;pop_back
15.3 关联容器
有序关联容器
multiset; set; multimap; map
无序管理容器
unordered_multiset; unordered_set; unordered_multimap; unordered_map
multiset
与set
和multimap
与map
之间的区别是是否可以允许具有重复的关键字
关联容器multiset
声明
//需要包含<set>头文件 #include<set> int main(){ const size_t SIZE=6; array<int, SIZE> a = {1, 2, 3, 4, 5, 6}; multiset<int, less<int> > intMultiset; }
注意:函数对象less<int>
的>
与声明的>
之前有空格,以防止流提取运算符>>
的影响
函数对象less<int>
表示创建的容器中的元素按照升序排列,递增是multiset
的默认排列顺序
成员函数
成员函数count
intMultiset.count(7);
:计算容器中值为7的元素个数
成员函数insert
intMultiset.insert(15); intMultiset.insert(intMultiset.cbegin()+2, 4); intMultiset.insert(a.cbegin(), a.cend());
一个参数:按照容器的排列顺序插入该元素
两个参数:
-
第一个参数为指定位置之后选择位置插入
-
第二个参数为插入的值
两个参数:
-
用两个迭代器指定一个范围的元素中插入元素
成员函数find
intMultiset.find(15);
:在容器中查找值为15的元素,并返回指向该元素的迭代器iterator
或const_iterator
;若未找到该元素,则返回与intMultiset.end()
相同的迭代器
成员函数lower_bound; upper_bound
intMultiset.lower_bound(15); intMultiset.upper_bound(15);
lower_bound
:返回值为15的元素第一次出现的位置的迭代器
upper_bound
:返回值为15的元素最后一次出现的位置的迭代器
成员函数equal_range
intMultiset.equal_range(15)
:返回一个pair
对象,包含lower_bound
和upper_bound
的返回值
auto p = intMultiset.equal_range(15); *(p.first); *(p.second);
可变参数类模板
pair
对象
包含lower_bound
和upper_bound
的返回值
tuple
对象
可以包含多种类型的多个对象
关联容器set
同关联容器multiset
,但是其不能插入容器内已拥有的重复元素
关联容器multimap
用于快速存取键-值对
声明
#include<map> int main(){ multimap<int, double, less<int> > intMultimap; multimap<int, double, less<int> > pairs = { {15, 2.7}, {24, 1.2}, {36, 4.9}, {42, 9.6} }//可以使用{}进行初始化 intMultimap.insert(make_pair(15, 2.7)); intMultimap.insert({15, 2.7}); }
函数make_pair()
用于创建一个pair
对象
使用给予范围for循环语句输出容器元素键值对
for(auto item: intMultimap) cout<<item.first<<"\t"<<item.second<<"\n";
关联容器map
与容器multimap
相似,但是不包含具有重复关键词的键-值对
可以使用下标[]进行访问
15.4 容器适配器
stack; queue; priority_queue
适配器stack
stack
可以使用任意序列容器vector; list; deque
来实现,默认为deque
声明
#include<stack> int main(){ stack<int> intDequeStack;//deque declare stack<int, vector<int> > intVectorStack;//vector declare stack<int, list<int> > intListStack;//list declare }
成员函数
成员函数pop; push
stack.pop()
:栈顶的元素出栈
stack.push()
:元素进栈,作为新的栈顶
成员函数top
stack.top()
:获取栈顶的元素
输出适配器栈的元素
template<typename T> void pushElements(T &stackRef){ for(int i = 0; i < 10; ++i){ stackRef.push(i); cout << stackRef.top() << ' '; } }//using function push and top to output element template<typename T> void popElements(T &stackRef){ for(int i = 0; i < 10; ++i){ cout << stackRef.top() << ' '; stackRef.pop(); } }//using function pop and top to output element
适配器queue
默认情况下使用deque
实现
声明
#include<queue> int main(){ queue<int> values; }
成员函数
成员函数pop; push
values.pop()
:删除队首的元素
values.push()
:在队尾插入元素
成员函数front; back
values.front()
:获取队首的元素值
values.back()
:获取队尾的元素值
适配器priority_queue
可以使用deque
或vector
实现,将优先级最高的元素放在队首
功能类似适配器queue
15.5 bitset
类
让创建和操作位集合更加容易
bitset<size> b;
:声明bitset
类,所有位都初始化为0(off)
b.set(bitNumber);
把bitNumber
位置的位设置为on
,表达式b.set()
将所有位置的位设为on
b.reset(bitNumber);
:把bitNumber
位置的位设置为off
,表达式b.set()
将所有位置的位设为off
b.flip(bitNumber);
:把bitNumber
位置的位反转,表达式b.flip()
把所有位置的位反转
b[bitNumber];
:返回bitNumber
位的引用
b.at(bitNumber);
返回bitNumber
的引用,会提供一次下标检查
b.test(bitNumber);
:进行越界检查,如果bitNumber
位为on
返回true
,反之返回false
b.size();
:返回bitset
类中的为个数
b.count();
:返回位被设置为on
的位的数量
b.any();
:有任意一个位为on
则返回true
b.all();
:所有位为on
则返回true
b.none();
:没有一个位为on
则返回true
b.to_string(); b.to_ulong();
:把b
变成一个字符串或者无符号长整数