一、STL
STL 提供了六大组件,彼此组合套用协同工作。这六大组件分别是:
容器(Containers):各种数据结构,如 vector、list、deque、set、map 等。从实现的角度来看,容器是一种 class template。
算法(Algorithms):各种常用算法,提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作,比如 sort、search、copy、erase。从实现的角度来看,STL 算法是一种 function template。
迭代器(Iterators):迭代器用于遍历对象集合的元素,扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有 5 种类型,以及其他衍生变化。从实现角度来看,迭代器是一种将 operator*、operator->、operator++、operator-- 等指针操作予以重载的 class template。所有的 STL 容器附带有自己专属的迭代器,因为只有容器设计者才知道如何遍历自己的元素。
仿函数(Functors):也称为函数对象(Function object),行为类似函数,可作为算法的某种策略。从实现角度来看,仿函数是一种重载了 operator() 的 class 或者 class template。
适配器(Adaptors):一种用来修饰容器或者仿函数或迭代器接口的东西。例如 STL 提供的 queue 和 stack,就是一种空间配接器,因为它们的底部完全借助于 deque。
分配器(Allocators):也称为空间配置器,负责空间的配置与管理。从实现的角度来看,配置器是一个实现了动态配置空间、空间管理、空间释放的 class template。
————————————————
版权声明:本文为CSDN博主「阿基米东」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lu_embedded/article/details/121668228
二、容器
容器分类:
1. 序列性容器:元素保持了在容器中的原始位置,允许在容器中指定插入、删除的位置,每个元素都有固定的位置,这个位置取决于插入的时间和地点。list
2. 关联性容器:元素的位置取决于容器特定的排序规则,与元素的值有关。map
2.1 list链表
C++ list(STL list)容器完全攻略(超级详细) (biancheng.net)
2.1.1 构造
list<int> lst;
list<int> lst2(3,1); //创建长度为3的链表,且初始化每个节点都为1
list<int> lst3{ 1,2,3,4 };
2.1.2 遍历
for (int v : lst2) {
cout << v << ' ';
}
cout << endl;
list<int>::iterator ite = lst3.begin();
while (ite != lst3.end()) {
cout << (*ite) << ' ';
ite++;
}
2.1.3 remove
删除所有值为val的元素
lst4.remove(2);
2.1.4 unique
将 连续、重复 的值缩简为1个
lst4.unique();
2.1.5 sort
排序
//lst4.sort(cmp_desc);
lst4.sort(greater<>()); //降序
lst4.sort(less<>()); //升序
2.1.6 reverse
翻转
lst4.reverse();
2.1.7 splice
剪切
list<int> lst5{ 10,3,6,9,2 };
//lst4.splice(++lst4.begin(), lst5); //剪切整个列表 粘贴位置,被剪列表
ite = lst5.begin();
advance(ite, 3); //往右偏移,注意越界
//lst4.splice(++lst4.begin(), lst5, ite); //剪切某个节点
lst4.splice(++lst4.begin(), lst5, ite, lst5.end()); //剪切某一段
2.1.8 merge
合并
list<int> lst6{ 4,5,60,72,80 };
list<int> lst7{ 1,9,20,40,79,92 };
//lst6.merge(lst7); //合并,前提是有序。剪切操作,合并后整体有序,默认升序
lst6.reverse();
lst7.reverse();
lst6.merge(lst7, greater<>());
out(lst6);
2.1.9 swap
交换
lst6.swap(lst7);
2.2 vector向量
2.2.1 构造
//vector<int> vec(4); //构造向量,使用量和容量都为4,默认值为0
//vector<int> vec(4,2); //构造向量,使用量和容量都为4,默认值为2
//vector<int> vec{ 1,2,3,4 };
int arr[] = { 6,2,4,6,7,3,2,4 };
vector<int> vec(arr + 1, arr + 7); //用数组给vector赋值
2.2.2 遍历
cout << v.size() << '-' << v.capacity() << endl;
vector<int>::iterator ite = v.begin();
while (ite!=v.end()){
cout << *ite << ' ';
ite++;
}
cout << endl;
2.2.3 增加删除
vec.push_back(30);
vec.pop_back();
2.2.4 insert插入
ite = vec.begin() + 2;
vec.insert(ite, 6);
2.2.5 erase删除
vec.erase(vec.begin() + 4);
out(vec);
ite = ++vec.begin();
//vec.erase(ite);
//此时ite会指向下一个,但是验证会出现异常
ite=vec.erase(ite); //参数中迭代器会失效,需要返回值
cout << *ite << endl;
2.2.5 clear
清空使用量
vec.clear(); //清空使用量
cout << vec.empty() << endl;
2.2.6 resize
重新指定使用量,删除多余的元素
vec.resize(4,2); //重新指定使用量,默认值为2
2.2.7 swap
交换
vector<int>().swap(vec);
vector<int>{1, 2}.swap(vec);
out(vec);
2.2.8 shrink_to_fit
缩容到合适大小
vec.shrink_to_fit(); //缩容到使用量大小
2.3 deque双端队列
分段连续
2.3.1 构造
deque<int> de{ 1,2,3,4 };
2.3.2 遍历
deque<int>::iterator ite = de.begin();
while (ite != de.end()) {
cout << *ite << ' ';
ite++;
}
cout << endl;
2.3.3 增加删除
de.push_back(5);
de.push_front(0);
de.pop_front();
de.pop_back();
2.3.4 下标
for (int i = 3; i < de.size(); i++)
de[i] = 100;
2.3.5 insert
de.insert(++de.begin(), 200);
2.3.6 erase
ite = de.begin() + 4;
ite = de.erase(ite);
cout << *ite << endl;
2.4 map映射表
红黑树
#include <iostream>
#include <map>
#include <string>
using namespace std;
/*
map:映射表 map的每一个元素,是键值对 pair,分为键值[key],实值(value)
键值唯一,不允许重复,根据键值默认排序(默认升序)
*/
int main() {
map<char,string> m; //定义一个空的mao
m['A'] = "an apple";
//m[键值]=实值;
m['B'] = "bee bee i'm sheep";
map<char, string>::iterator ite = m.begin();
while (ite!=m.end()){
//first键值 second 实值
cout << ite->first << '-' << ite->second << " ";
ite++;
}
cout << endl;
m.insert(pair<char, string>('D', "what does dog say"));
for (pair<char, string> pr : m) {
cout << pr.first << "-" << pr.second << ' ';
}
cout << endl;
m['D'] = "114514"; //如果键值存在,则修改实值
m.insert(pair<char, string>('D', "1919810")); //键值存在,则失败
for (pair<char, string> pr : m) {
cout << pr.first << "-" << pr.second << ' ';
}
cout << endl;
ite = ++m.begin();
ite = m.erase(ite); //按位置删除
cout << ite->first << "-" << ite->second << endl;
for (pair<char, string> pr : m) {
cout << pr.first << "-" << pr.second << ' ';
}
cout << endl;
ite = m.find('E'); //查找某个键值,返回指向元素的迭代器
if (ite != m.end()) //找到了
cout << ite->first << "-" << ite->second << endl;
else cout << "no founds" << endl;
cout << m.count('A') << endl; //统计键值出现的次数,map键值唯一,结果1 0
cout << m.size() << endl; //元素数量
m.clear(); //清空map
}
2.4.1 构造
map<char, int> m1{ {'B',1},{'D',2},{'C',3},{'A',4} };
2.4.2 遍历
map<char, int>::iterator ite = m.begin();
while (ite != m.end()) {
cout << ite->first << '-' << (*ite).second << " ";
ite++;
}
for (pair<char, int>pr : m1) {
cout << pr.first << '-' << pr.second << ' ';
}
2.4.3 下标操作
m1['B'] = 10; //键值存在 则修改,不存在 则添加元素
2.4.4 insert
pair<map<char, int>::iterator, bool>pr1 = m1.insert(pair<char, int>('F', 7));
out(m1);
pair<map<char, int>::iterator, bool>pr2 = m1.insert(pair<char, int>('F', 9));
out(m1);
cout << pr1.first->first << ' ' << pr1.first->second << ' ' << pr1.second << endl; //1
cout << pr2.first->first << ' ' << pr2.first->second << ' ' << pr2.second << endl; //0
//成功返回新插入的元素,失败返回已存在的元素
2.4.5 find
ite = m1.find('C');
ite = m1.erase(ite);
2.4.6 lower_bound upper_bound
ite = m1.lower_bound('B');
cout << ite->first << "-" << ite->second << endl;
ite = m1.upper_bound('C');
cout << ite->first << "-" << ite->second << endl;
注意:键值不允许被修改
2.5 set集合
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> st{ 3,6,1,2,0,4 };
for (int v : st) {
cout << v << ' ';
}
cout << endl;
st.insert(7);
set<int>::iterator ite = st.begin();
while (ite!=st.end()){
cout << *ite << " ";
ite++;
}
cout << endl;
}
2.6 hash_map哈希表
空间换时间 O(1)
#include<iostream>
#include<unordered_map>
using namespace std;
int main() {
unordered_map<int, string> m{ {34,"33"},{5,"55"},{31,"11"} };
for (pair<int, string>pr : m) {
cout << pr.first << '-' << pr.second << ' ';
}
cout << endl;
m.insert(pair<int, string>(3, "0"));
m.insert(pair<int, string>(33, "13"));
m.insert(pair<int, string>(43, "84"));
//unordered_map<int, string>::iterator ite = m.begin();
auto ite = m.begin();
while (ite != m.end()) {
cout << ite->first << '-' << ite->second << ' ';
ite++;
}
cout << endl;
ite = m.find(3);
cout << ite->first << "-" << ite->second << endl;
}
三、算法
#include<iostream>
#include<algorithm>
#include<list>
#include<vector>
#include<map>
using namespace std;
void show(int a) {
cout << a << ' ';
}
int tot;
void fun(int a) {
tot += a;
}
int main() {
list<int> lst{ 2,3,4,5,6,7 };
for_each(lst.begin(), lst.end(), &show);
cout << endl;
vector<int> vec{ 1,2,3,4,5,6,7 };
for_each(vec.begin(), vec.end(), &fun);
cout << tot << endl;
cout << count(vec.begin(), vec.end(), 3) << endl;
auto iteEnd = lst.begin();
advance(iteEnd, 5);
cout << count(lst.begin(), iteEnd, 3) << endl;
cout << equal(++vec.begin(), vec.end(), lst.begin()) << endl;
auto iteLst = find(lst.begin(), lst.end(), 3);
cout << *iteLst << endl;
cout << *++iteLst << endl;
auto iFind = find(vec.begin(), vec.begin() + 2, 4);
if (iFind != vec.begin() + 2)
cout << "找到了";
else cout << "没找到";
cout << endl;
sort(vec.begin(), vec.end(), greater<>());
for_each(vec.begin(), vec.end(), &show);
}
四、迭代器
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> lst{ 1,2,3,4 };
list<int>::iterator ite = lst.begin(); //正向迭代器
list<int>::reverse_iterator iteRev = lst.rbegin(); //反向迭代器
while (iteRev != lst.rend()) {
cout << *iteRev << " ";
iteRev++;
}
cout << endl;
iteRev = lst.rbegin();
while (iteRev != lst.crend()) {
if (*iteRev == 2) {
ite = iteRev.base(); //将反向迭代器转为正向
cout << *ite << endl;
ite = lst.erase(--ite);
break;
}
++iteRev;
}
iteRev = lst.rbegin();
while (iteRev != lst.rend()) {
cout << *iteRev << " ";
iteRev++;
}
cout << endl;
}
五、容器适配器
5.1 栈stack
后入先出(Last In First Out,LIFO)
5.2 队列queue
先入先出(First In First Out,FIFO)
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
int main() {
stack<int> t;
t.push(1);
t.push(2);
t.push(3);
t.push(4);
t.push(5);
while (t.size()) {
cout << t.top() << " ";
t.pop();
}
cout << endl;
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
cout << q.back() << " ";
while (!q.empty()) {
cout << q.front() << ' ';
q.pop();
}
cout << endl;
}
5.3 仿函数
#include<iostream>
using namespace std;
int add(int a, int b) {
return a + b;
}
class Cadd {
public:
int sum = 0;
int operator() (int a, int b) {
sum += a + b;
return a + b;
}
};
int main() {
Cadd a;
cout << a(1, 2) << endl;
cout << a(5, 6) << endl;
cout << a.sum << endl;
}