Cpp Standard Library 简明教程
C++ STL - Cheat Sheet
此 C++ STL 备忘表涵盖了从基本 STL(如 vectors 、 hashmaps 、集合等)到高级概念(如 functors 、 iterators 等)的广泛主题。它专为希望快速通读关键概念及其语法和相关示例的程序员而设计。
STL Containers
STL 容器模板类包含数据结构,如 Dynamic Arrays (或向量、链表)、散列表、哈希集、 Trees 、 Linked Lists 等。这些用于存储和执行数据操作。
容器模板具有以下部分:
-
Sequential Containers
-
Container Adapters
-
Associative Containers
-
Unordered Containers
每个容器都有各自的头文件,可以在程序开始时包含该文件。例如,std::vector 包含在 #include<vector> 库中。
Unordered Containers
无序容器类似于关联容器,但唯一的区别在于它们不存储已排序的数据。不过,这些容器使用键值对提供快速搜索时间。它们为:
-
Unordered Multiset
现在我们已经建立了所有容器的学习图,我们将用一个示例代码简单解释 STL 中的每个容器 −
Vector in STL
vector 在运行时初始化为一个动态数组,并且它的容量是可变的。可在 C++ <vector> 头文件找到它。
vector<data_type> vec1; //1D vector
vector<vector<data_type>> vec2; //2D vector
vector<container_type<data_type>> vec3; //2D vector of other container
vector<data_type> vec1(n); //vector of size n
vector<data_type> vec1(n,k); // vector of size n, with each element=k
vector template 中有不同的函数。这些函数在下面的表中得到简要解释 −
S.No. |
Function |
Function Explanation |
TC |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素的理论元素后的迭代器。 |
O(1) |
|
3. |
返回存在的元素数量。 |
O(1) |
|
4. |
如果 vector 为空则返回 true,否则返回 false。 |
O(1) |
|
5. |
返回特定位置的元素。 |
O(1) |
|
6. |
为 vector 元素分配一个新值。 |
O(n) |
|
7. |
在 vector 的末尾添加一个元素。 |
O(1) |
|
8. |
从末尾删除一个元素。 |
O(1) |
|
9. |
在指定位置插入一个元素。 |
O(n) |
|
10. |
删除特定位置或范围内的元素。 |
O(n) |
|
11. |
Removes all elements. |
O(n) |
此处,TC 表示 vector 模板的不同成员函数的时间复杂性。有关时间复杂性的更多信息,请访问此文章 − Time complexity 。
// C++ program to illustrate the vector container
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n=2;
vector<int> vec1 = { 1, 2, 3, 4, 5 };
vector<int> vec2(n,0);
vector<vector<int>> vec3(n,vector<int>(2*n,1));
vec1.push_back(6);
cout << "vec1: ";
for (int i = 0; i < vec1.size(); i++) {
cout << vec1[i] << " ";
}
cout << endl<<"vec2: ";
for (int i = 0; i < vec2.size(); i++) {
cout << vec2[i] << " ";
}
cout << endl;
vec1.erase(vec1.begin() + 4);
cout << "vec1 after erasing: ";
for (auto i = vec1.begin(); i != vec1.end(); i++) {
cout << *i << " ";
}
cout << endl;
cout << "vec3:-" << endl;
for (auto i : vec3) {
for (auto j : i) {
cout << j << " ";
}
cout << endl;
}
cout << endl;
vector<pair<int,int>> vec4;
vec4.push_back({2,3});
vec4.push_back({4,3});
cout<<"vector of pairs, vec4 : "<<endl;
for(auto i: vec4){
cout<<i.first<<" "<<i.second<<endl;
}
return 0;
}
vec1: 1 2 3 4 5 6
vec2: 0 0
vec1 after erasing: 1 2 3 4 6
vec3:-
1 1 1 1
1 1 1 1
vector of pairs, vec4 :
2 3
4 3
List in STL
list 容器初始化为 doubly linked list ,而对于实现 singly linked list ,我们使用 forward_list 。可在 C++ <list> 头文件找到它。
list<data_type> list1;
list template 中有不同的函数。这些函数在下面的表中得到简要解释 −
S.No. |
Function |
Function Explanation |
TC |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素的理论元素后的迭代器。 |
O(1) |
|
3. |
返回列表中的元素数量。 |
O(1) |
|
4. |
在列表末尾添加一个元素。 |
O(1) |
|
5. |
从尾部移除一个元素。 |
O(1) |
|
6. |
在列表的前面添加一个元素。 |
O(1) |
|
7. |
从头部移除一个元素。 |
O(1) |
|
8. |
在指定位置插入一个元素。 |
O(n) |
|
9. |
删除指定位置的元素。 |
O(n) |
|
10. |
从列表中移除所有给定元素的副本。 |
O(n) |
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main(){
list<int> list1 = { 1, 5, 9, 1, 4, 6 };
cout << "List1 first and last element: " << list1.front() <<" "<<list1.back()<<endl;
// adding element
list1.insert(list1.begin(), 5);
// deleting element
list1.erase(list1.begin());
// traversing list1
cout << "list1: ";
for (auto i = list1.begin(); i != list1.end(); i++) {
cout << *i << " ";
}
cout << endl;
return 0;
}
List1 first and last element: 1 6
list1: 1 5 9 1 4 6
Deque in STL
deque 容器被初始化为 doubly ended queue ,元素可以从队列的两端进行压入和弹出。它可以在 C++ <deque> 头文件中找到。
deque<data_type> dq1;
deque template 中有不同的函数。这些函数在下面的表格中进行了简要说明 −
S.No. |
Function |
Function Explanation |
TC |
1. |
返回到第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素的理论元素后的迭代器。 |
O(1) |
|
3. |
Access specified element. |
O(1) |
|
4. |
访问给定索引处的元素。 |
O(1) |
|
5. |
Returns the first element. |
O(1) |
|
6. |
Returns the last element. |
O(1) |
|
7. |
返回元素数量。 |
O(1) |
|
8. |
在末尾添加元素。 |
O(1) |
|
9. |
从末尾移除元素。 |
O(1) |
|
10. |
在前面添加元素。 |
O(1) |
|
11. |
从头部移除元素。 |
O(1) |
#include <deque>
#include <iostream>
using namespace std;
int main(){
deque<int> dq = { 1, 2, 3, 4, 5 ,6, 8 };
cout<<"Initial Deque: "<<endl;
for (auto i : dq) {
cout << i << " ";
}
cout<<endl;
dq.push_front(dq.back());
dq.pop_back();
for (auto i : dq) {
cout << i << " ";
}
cout<<endl;
dq.push_front(dq.back());
dq.pop_back();
for (auto i : dq) {
cout << i << " ";
}
cout<<endl;
dq.pop_back();
dq.pop_front();
for (auto i : dq) {
cout << i << " ";
}
cout<<endl;
dq.push_front(11);
dq.push_back(99);
for (auto i : dq) {
cout << i << " ";
}
return 0;
}
Initial Deque:
1 2 3 4 5 6 8
8 1 2 3 4 5 6
6 8 1 2 3 4 5
8 1 2 3 4
11 8 1 2 3 4 99
Stack in STL
栈容器被初始化为 LIFO container ,元素可以压入顶部,并从顶部弹出。因此,最后一个进入栈的元素是第一个从容器中退出的元素。它可以在 C++ <stack> 头文件中找到。
stack<data_type> s1;
stack template 中有不同的函数。这些函数在下面的表格中进行了简要说明 −
S.No. |
Function |
Function Explanation |
TC |
1. |
如果栈为空,则返回 true,否则返回 false。 |
O(1) |
|
2. |
返回栈中的元素数量。 |
O(1) |
|
3. |
Returns the top element. |
O(1) |
|
4. |
在堆栈中推送一个元素。 |
O(1) |
|
5. |
从堆栈中移除一个元素。 |
O(1) |
// C++ Program to illustrate the stack
#include <bits/stdc++.h>
using namespace std;
int main(){
stack<int> s;
s.push(2);
s.push(9);
s.push(3);
s.push(1);
s.push(6);
cout << "Top is: " << s.top() << endl;
while (!s.empty()) {
cout<<"size is: "<<s.size()<<" ";
cout << "element is: "<<s.top() << endl;
s.pop();
}
return 0;
}
Top is: 6
size is: 5 element is: 6
size is: 4 element is: 1
size is: 3 element is: 3
size is: 2 element is: 9
size is: 1 element is: 2
Queue in STL
队列容器初始化为 FIFO container ,其中可以将元素推送到前面,并从前面弹出。因此,第一个进入的元素是第一个从容器中退出的元素。它可以在 C++ <queue> 头文件中找到。
queue<data_type> q1;
queue template 中有不同的函数。它们在下面的表中进行简要解释 −
S.No. |
Function |
Function Explanation |
TC |
1. |
如果队列为空,则返回 true,否则返回 false。 |
O(1) |
|
2. |
返回队列中的项目数。 |
O(1) |
|
3. |
Returns the front element. |
O(1) |
|
4. |
返回末尾的元素。 |
O(1) |
|
5. |
向队列添加一个项目。 |
O(1) |
|
6. |
从队列中移除一个项目。 |
O(1) |
#include <iostream>
#include <queue>
using namespace std;
int main(){
queue<int> q;
q.push(1);
q.push(1);
q.push(6);
q.push(1);
cout << "Front element: " << q.front() << endl;
cout << "Back element: " << q.back() << endl;
cout << "q: ";
int size = q.size();
for (int i = 0; i < size; i++) {
cout << q.front() << " ";
q.pop();
}
return 0;
}
Front element: 1
Back element: 1
q: 1 1 6 1
Hash-Set/Set in STL
集合容器被初始化为唯一元素存储数据结构,它还实现了排序顺序,既可以升序也可以降序。它通常实现 red-black tree 作为底层数据结构。它可以在 C++ <set> 头文件中找到。
set<data_type> set;
set<data_type, greater<data_type>> set2; //this is a set in descending order
set<data_type, comparator/lambda_function> set3; //this is a set in custom order
set template 中有不同的函数。它们在下面的表中进行简要解释 −
S.No. |
Function |
Function Explanation |
TC |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素的迭代器。 |
O(1) |
|
3. |
返回元素数量。 |
O(1) |
|
4. |
检查容器是否为空。 |
O(1) |
|
5. |
Inserts a single element. |
O(logn) |
|
6. |
Removes the given element. |
O(logn) |
|
7. |
Removes all elements. |
O(n) |
|
8. |
如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。 |
O(logn) |
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main(){
set<int> set;
set.insert(9);
set.insert(11);
set.insert(9);
set.insert(11);
bool flag=set.find(9)!=set.end();
cout<<"Is there a 9 in the set? "<<flag<<endl;
set.insert(21);
for (auto i : set) {
cout << i << " ";
}
cout << endl;
return 0;
}
Is there a 9 in the set? 1
9 11 21
Hash-Map/Map in STL
映射是一个容器,它以密钥的排序顺序以键值对的形式存储数据,其中每个密钥都是唯一的。它使用红黑树数据结构实现。它包含在 <map> 头文件中。
map<key_type,value_type> map;
map template 中有不同的函数。它们在下面的表中进行简要解释 −
S.No. |
Function |
Function Explanation |
TC |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素之后的理论元素的迭代器 |
O(1) |
|
3. |
返回映射中的元素数 |
O(1) |
|
4. |
向映射中添加一个新元素。 |
O(logn) |
|
5. |
删除迭代器所指向位置的元素。 |
O(logn) |
|
6. |
删除键及其值从映射。 |
O(logn) |
|
7. |
删除地图中的所有元素。 |
O(n) |
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(){
map<char,int> map;
string s="abbacdbbac";
for(char c: s){
map[c]++;
}
for(auto it:map){
cout<<it.first<<" : "<<it.second<<endl;
}
cout<<"after erasing element 'c' : "<<endl;
map.erase('c');
for(auto it:map){
cout<<it.first<<" : "<<it.second<<endl;
}
return 0;
}
a : 3
b : 4
c : 2
d : 1
after erasing element 'c' :
a : 3
b : 4
d : 1
Unordered Set in STL
无序集容器存储唯一的数值,但与 set 的唯一区别是数据不会以任何顺序存储。它使用 <unordered_set> 头文件实现。
unordered_set<data_type> set;
unordered_set template 中有不同的函数。下表对其作了简要说明:
S. No. |
Functions |
Description |
Time Complexity |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素之后的理论元素的迭代器 |
O(1) |
|
3. |
返回元素数量。 |
O(1) |
|
4. |
如果无序集为空,则返回 true,否则返回 false。 |
O(1) |
|
5. |
在容器中插入一项。 |
O(1) |
|
6. |
从容器中移除一个元素。 |
O(1) |
|
7. |
如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。 |
O(1) |
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;
int main(){
unordered_set<int> set;
set.insert(19);
set.insert(10);
set.insert(13);
set.insert(21);
bool flag=set.find(9)!=set.end();
cout<<"Is there a 9 in the set? "<<flag<<endl;
set.insert(21);
for (auto i : set) {
cout << i << " ";
}
cout << endl;
return 0;
}
Is there a 9 in the set? 0
21 13 10 19
Unordered Map in STL
在无序映射容器中,数据的存储类似于映射容器,但存储数据的顺序是随机的,因此不遵循升序或降序。它包含在 <unordered_map> 标头文件中。
unordered_map<key_type, value_type> map;
unordered_map template 中有不同的函数。下表对其作了简要说明:
S. No. |
Function |
Description |
Time Complexity |
1. |
返回指向第一个元素的迭代器。 |
O(1) |
|
2. |
返回指向最后一个元素之后的理论元素的迭代器 |
O(1) |
|
3. |
返回元素数量。 |
O(1) |
|
4. |
如果无序映射为空,则返回 true,否则返回 false。 |
O(1) |
|
5. |
如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。 |
O(1) |
|
6. |
返回数据存储的存储桶编号。 |
O(1) |
|
7. |
在容器中插入一项。 |
O(1) |
|
8. |
从容器中移除一个元素。 |
O(1) |
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int main(){
unordered_map<char,int> map;
string s="abbacdbbac";
for(char c: s){
map[c]++;
}
for(auto it:map){
cout<<it.first<<" : "<<it.second<<endl;
}
cout<<"after erasing element 'c' : "<<endl;
map.erase('c');
for(auto it:map){
cout<<it.first<<" : "<<it.second<<endl;
}
return 0;
}
d : 1
c : 2
b : 4
a : 3
after erasing element 'c' :
d : 1
b : 4
a : 3
Functors in C++ STL
函数对象或函数对象,是 C++ STL 中的行为类似于方法/函数的对象。这些包括在 <functional> 头文件中。这些需要 () parenthesis operator. 的重载。
C++ STL 中的主要函数对象如下:
Non-member functions
Sr.No. |
Non-member functions |
Definition |
1 |
专门用于 std::swap 算法 |
|
2 |
将 std::function 与 nullptr 比较 |
Operator classes
Sr.No. |
Operator classes |
Definition |
1 |
这是一个按位 AND 函数对象类 |
|
2 |
这是一个按位 OR 函数对象类 |
|
3 |
这是一个按位 XOR 函数对象类 |
|
3 |
这是一个除法函数对象类 |
|
4 |
这是一个用于比较相等性的函数对象类 |
|
5 |
这是一个用于比较大于的函数对象类 |
|
6 |
这是一个用于比较大于或等于的函数对象类 |
|
7 |
这是一个用于比较小于的函数对象类 |
|
8 |
这是一个用于比较小于或等于的函数对象类 |
|
9 |
这是一个逻辑 AND 函数对象类 |
|
10 |
这是一个逻辑 NOT 函数对象类 |
|
11 |
这是一个逻辑 OR 函数对象类 |
|
12 |
这是一个减法函数对象类 |
|
13 |
这是一个模数函数对象类 |
|
14 |
这是一个乘法函数对象类 |
|
15 |
这是一个取负函数对象类 |
|
16 |
它是非相等比较的函数对象类 |
|
17 |
它是一个函数对象类 |
Example
#include <functional>
#include <iostream>
using namespace std;
int main(){
equal_to<int> obj1;
not_equal_to<int> obj2;
greater<int> obj3;
less<int> obj4;
plus<int> obj5;
minus<int> obj6;
cout << "Functors and their usage: \n";
cout << "Are these equal? " << obj1(11, 22) << endl;
cout << "Are these different? " << obj2(11, 22) << endl;
cout << "Is first index greater than second? " << obj3(10, 20) << endl;
cout << "Is first index smaller than second? " << obj4(10, 2) << endl;
cout << "After adding: " << obj5(10, 20) << endl;
cout << "After subtracting: " << obj6(10, 8) << endl;
return 0;
}
Functors and their usage:
Are these equal? 0
Are these different? 1
Is first index greater than second? 0
Is first index smaller than second? 0
After adding: 30
After subtracting: 2
Algorithms in C++ STL
在 C++ STL 中,算法模板为用户提供多种操作,这些操作对于实现关键算法至关重要,例如 searching 、 sorting 、从容器返回 maximum/minimum value 等。可以使用 <algorithm> 头部访问这些算法。
C++ 中的 <algorithm> 库提供多种有用的函数。下面给出一些最常用的函数:
sort() in C++
sort() 算法用于按升序、降序或自定义顺序对给定数据进行排序(使用 comparator 或 lambda function )。
sort(start_iterator,end_iterator)
sort(start,end, comparator_function) //for custom sorting
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main(){
vector<int> v = {999, 1252, 3117, 122222 , 10, 88, 2, 9, 45, 82, 546, 42, 221 , -1};
cout<<"Ascending order: ";
sort(v.begin(),v.end());
for(int i:v) cout<<i<<" ";
cout<<endl;
cout<<"Descending order: ";
sort(v.begin(),v.end(),greater<int>());
for(int i:v) cout<<i<<" ";
cout<<endl;
return 0;
}
Ascending order: -1 2 9 10 42 45 82 88 221 546 999 1252 3117 122222
Descending order: 122222 3117 1252 999 546 221 88 82 45 42 10 9 2 -1
copy() in C++
Copy() 算法用于将元素从一个容器复制到另一个容器。
copy(start_iterator,end_iterator, destination_operator)
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main(){
vector<int> v = { 1, 2, 3, 4, 5 , 4 ,3 , 2, 1};
vector<int> newvec(9);
copy(v.begin(), v.end(), newvec.begin());
for(int &i:newvec) cout<<i<<" ";
cout<<endl;
return 0;
}
1 2 3 4 5 4 3 2 1
find() in C++
find() 算法用于在给定元素范围内查找关键元素。
find (firstIterator, lastIterator, value);
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> v= { 1,3,5,2,3,1,55,41};
// finding 5
auto itr = find(v.begin(), v.end(), 55);
if (itr != v.end()) {
cout << *itr << " Element found !!!" << endl;
}else {
cout << "Element not present !!!" << endl;
}
return 0;
}
55 Element found !!!
max_element() and min_element() in C++
max_element() 和 min_element() 用于在给定元素范围内查找最大值和最小值。
max_element (firstIterator, lastIterator);
min_element (firstIterator, lastIterator);
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main(){
vector<int> v = {999, 1252, 3117, 122222 , 10, 88, 2, 9, 45, 82, 546, 42, 221 , -1};
cout << "Maximum Element: " << *max_element(v.begin(),v.end())<<endl;
cout<<"Minimum Element: "<<*min_element(v.begin(),v.end()) <<"\n";
return 0;
}
Maximum Element: 122222
Minimum Element: -1
for_each in C++
for_each() 算法用于对容器中元素的范围应用给定的操作或指令。
for_each (firstIterator, lastIterator, unaryFunction);
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main(){
vector<int> vec1 = { 1, 2, 3, 4, 5 };
for_each(vec1.begin(), vec1.end(), [](int& i){
i++;
});
for(int i:vec1) cout<<i<<" ";
cout<<endl;
return 0;
}
2 3 4 5 6
swap() in C++
swap() 算法用于就地用一个元素替换另一个元素,因此元素会交换位置。
swap(container1,container2)
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> vec1 = {1, 2, 3};
vector<int> vec2 = {4, 5, 6};
swap(vec1,vec2);
cout<<"vec 1: "<<endl;
for(int i:vec1) cout<<i<<" ";
cout<<endl;
cout<<"vec 2: "<<endl;
for(int i:vec2) cout<<i<<" ";
cout<<endl;
return 0;
}
vec 1:
4 5 6
vec 2: 1 2 3