Cpp Standard Library 简明教程

C++ STL - Cheat Sheet

此 C++ STL 备忘表涵盖了从基本 STL(如 vectorshashmaps 、集合等)到高级概念(如 functorsiterators 等)的广泛主题。它专为希望快速通读关键概念及其语法和相关示例的程序员而设计。

Introduction

标准模板库 (STL) 是一个 C library ,它包含所有 classfunction 模板。它用于实现基本数据结构(如 HashsetHeapList 等)和函数(如数学、算法等),并包含 C 编程语言中可用的所有 containers

Components of STL

标准模板库包含若干个容器和函数,可以按以下方式进行分类:

  1. Containers

  2. Functors

  3. Algorithms

  4. Iterators

STL Containers

STL 容器模板类包含数据结构,如 Dynamic Arrays (或向量、链表)、散列表、哈希集、 TreesLinked Lists 等。这些用于存储和执行数据操作。

容器模板具有以下部分:

  1. Sequential Containers

  2. Container Adapters

  3. Associative Containers

  4. Unordered Containers

每个容器都有各自的头文件,可以在程序开始时包含该文件。例如,std::vector 包含在 #include<vector> 库中。

Sequential Containers

顺序容器使用顺序访问来实现数据结构。它们包括:

Container Adapters

容器适配器通过为顺序容器提供不同的接口来实现队列、堆栈等数据结构。它们包括:

Associative Containers

关联容器用于存储有序数据,可以使用这些数据的键值快速进行搜索。它们包括:

  1. Set

  2. Multiset

  3. Map

  4. Multimap

Unordered Containers

无序容器类似于关联容器,但唯一的区别在于它们不存储已排序的数据。不过,这些容器使用键值对提供快速搜索时间。它们为:

现在我们已经建立了所有容器的学习图,我们将用一个示例代码简单解释 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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素的理论元素后的迭代器。

O(1)

3.

size()

返回存在的元素数量。

O(1)

4.

empty()

如果 vector 为空则返回 true,否则返回 false。

O(1)

5.

at()

返回特定位置的元素。

O(1)

6.

assign()

为 vector 元素分配一个新值。

O(n)

7.

push_back()

在 vector 的末尾添加一个元素。

O(1)

8.

pop_back()

从末尾删除一个元素。

O(1)

9.

insert()

在指定位置插入一个元素。

O(n)

10.

erase()

删除特定位置或范围内的元素。

O(n)

11.

clear()

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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素的理论元素后的迭代器。

O(1)

3.

size()

返回列表中的元素数量。

O(1)

4.

push_back()

在列表末尾添加一个元素。

O(1)

5.

pop_back()

从尾部移除一个元素。

O(1)

6.

push_front()

在列表的前面添加一个元素。

O(1)

7.

pop_front()

从头部移除一个元素。

O(1)

8.

insert()

在指定位置插入一个元素。

O(n)

9.

erase()

删除指定位置的元素。

O(n)

10.

remove()

从列表中移除所有给定元素的副本。

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.

begin()

返回到第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素的理论元素后的迭代器。

O(1)

3.

at()

Access specified element.

O(1)

4.

[ ]

访问给定索引处的元素。

O(1)

5.

front()

Returns the first element.

O(1)

6.

back()

Returns the last element.

O(1)

7.

size()

返回元素数量。

O(1)

8.

push_back()

在末尾添加元素。

O(1)

9.

pop_back()

从末尾移除元素。

O(1)

10.

push_front()

在前面添加元素。

O(1)

11.

pop_front()

从头部移除元素。

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.

empty()

如果栈为空,则返回 true,否则返回 false。

O(1)

2.

size()

返回栈中的元素数量。

O(1)

3.

top()

Returns the top element.

O(1)

4.

push(x)

在堆栈中推送一个元素。

O(1)

5.

pop()

从堆栈中移除一个元素。

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.

empty()

如果队列为空,则返回 true,否则返回 false。

O(1)

2.

size()

返回队列中的项目数。

O(1)

3.

front()

Returns the front element.

O(1)

4.

back()

返回末尾的元素。

O(1)

5.

push()

向队列添加一个项目。

O(1)

6.

pop()

从队列中移除一个项目。

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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素的迭代器。

O(1)

3.

size()

返回元素数量。

O(1)

4.

empty()

检查容器是否为空。

O(1)

5.

insert()

Inserts a single element.

O(logn)

6.

erase()

Removes the given element.

O(logn)

7.

clear()

Removes all elements.

O(n)

8.

find()

如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。

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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素之后的理论元素的迭代器

O(1)

3.

size()

返回映射中的元素数

O(1)

4.

insert()

向映射中添加一个新元素。

O(logn)

5.

erase(iterator)

删除迭代器所指向位置的元素。

O(logn)

6.

erase(key)

删除键及其值从映射。

O(logn)

7.

clear()

删除地图中的所有元素。

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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素之后的理论元素的迭代器

O(1)

3.

size()

返回元素数量。

O(1)

4.

empty()

如果无序集为空,则返回 true,否则返回 false。

O(1)

5.

insert()

在容器中插入一项。

O(1)

6.

erase()

从容器中移除一个元素。

O(1)

7.

find()

如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。

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.

begin()

返回指向第一个元素的迭代器。

O(1)

2.

end()

返回指向最后一个元素之后的理论元素的迭代器

O(1)

3.

size()

返回元素数量。

O(1)

4.

empty()

如果无序映射为空,则返回 true,否则返回 false。

O(1)

5.

find()

如果存在,则返回指向给定元素的指针,否则返回指向末尾的指针。

O(1)

6.

bucket()

返回数据存储的存储桶编号。

O(1)

7.

insert()

在容器中插入一项。

O(1)

8.

erase()

从容器中移除一个元素。

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 中的主要函数对象如下:

Member functions

Sr.No.

Member functions

Definition

1

(constructor)

它用于构造一个新的 std::function 实例

2

(destructor)

它用于销毁 std::function 实例

3

operator=

它用于分配新目标

4

swap

它用于交换内容

5

assign

它用于分配新目标

6

operator bool

它用于检查是否包含有效目标

7

operator()

用于调用目标

Non-member functions

Sr.No.

Non-member functions

Definition

1

std::swap

专门用于 std::swap 算法

2

operator== operator!=

将 std::function 与 nullptr 比较

Operator classes

Sr.No.

Operator classes

Definition

1

bit_and

这是一个按位 AND 函数对象类

2

bit_or

这是一个按位 OR 函数对象类

3

bit_xor

这是一个按位 XOR 函数对象类

3

divides

这是一个除法函数对象类

4

equal_to

这是一个用于比较相等性的函数对象类

5

greater

这是一个用于比较大于的函数对象类

6

greater_equal

这是一个用于比较大于或等于的函数对象类

7

less

这是一个用于比较小于的函数对象类

8

less_equal

这是一个用于比较小于或等于的函数对象类

9

logical_and

这是一个逻辑 AND 函数对象类

10

logical_not

这是一个逻辑 NOT 函数对象类

11

logical_or

这是一个逻辑 OR 函数对象类

12

minus

这是一个减法函数对象类

13

modulus

这是一个模数函数对象类

14

multiplies

这是一个乘法函数对象类

15

negate

这是一个取负函数对象类

16

not_equal_to

它是非相等比较的函数对象类

17

plus

它是一个函数对象类

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 中,算法模板为用户提供多种操作,这些操作对于实现关键算法至关重要,例如 searchingsorting 、从容器返回 maximum/minimum value 等。可以使用 <algorithm> 头部访问这些算法。

C++ 中的 <algorithm> 库提供多种有用的函数。下面给出一些最常用的函数:

  1. Sort

  2. Copy

  3. Find

  4. Max Element and Min Element

  5. For Each

  6. Swap

sort() in C++

sort() 算法用于按升序、降序或自定义顺序对给定数据进行排序(使用 comparatorlambda 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

Iterators in C++ STL

迭代器可以看作用于按顺序遍历容器的指针。这些迭代器在 C++ 中使用 <iterator> 头文件包含。

每个容器都有自己的迭代器。为避免混乱,我们在遍历容器时可以使用 ‘auto’ 关键字定义迭代器。

迭代器有五种类型:

  1. Input Iterator

  2. Output Iterator

  3. Forward Iterator

  4. Bi-Directional Iterator

  5. Random Iterator

Example

#include <bits/stdc++.h>
using namespace std;

int main(){
   vector<int> myvec={1,5,2,4,3,6,6,9,8};
   set<int>set(myvec.begin(),myvec.end());

   for(auto itr:myvec) cout<<itr<<" ";
      cout<<endl;
   for(auto itr:set) cout<<itr<<" ";
      cout<<endl;

   return 0;
}
1 5 2 4 3 6 6 9 8
1 2 3 4 5 6 8 9