C++常用STL (容器类 、容器适配器 、迭代器 和 算法)

【C++】 STL详解

若有错误,请多指正!

什么是 STL

C++ 中的 STL(Standard Template Library),即 标准模板库,是 C++ 标准库中的一个组成部分。它提供了一套丰富的模板类、函数和算法,用于简化常用数据结构和算法的实现,提高代码的复用性和可维护性。

STL 包括三个主要组件:

  • 容器(Containers):提供了几种不同类型的容器,例如 vector、list、map、set、queue 和 stack 等,每种容器都有其特定的功能和性能特征,以满足不同的需要。

  • 迭代器(Iterators):提供了一套通用的迭代器接口,它们可以遍历各种容器中的元素,为算法实现提供统一的接口。

  • 算法(Algorithms):提供了一系列通用的算法,例如排序、查找、计数、变换等。这些算法可以适用于各种容器类型,并具有良好的性能和可读性。

STL 的优点在于它提供了一套通用、高效、安全、标准的工具集,使得程序员可以更加容易地实现常用的数据结构和算法,同时也可以编写出安全、易读、高效的代码,从而降低了开发和维护的难度。

容器类

C++ STL 中所有的容器类如下:

  1. 序列式容器(Sequence Containers):
  • vector:动态数组,支持随机访问,可动态扩展大小。
  • deque:双端队列,支持双向访问,可高效插入删除首尾元素。
  • list:双向链表,支持顺序访问,可高效插入删除。
  1. 关联式容器(Associative Containers):
  • set:基于红黑树实现的无序集合,元素唯一,并按照从小到大排列。
  • multiset:基于红黑树实现的无序集合,元素可重复,并按照从小到大排列。
  • map:基于红黑树实现的关联数组,键值对存储,自动排序。
  • multimap:基于红黑树实现的关联数组,键可以重复,键值对按照插入顺序存储。
  1. 无序关联式容器(Unordered Associative Containers):
  • unordered_set:基于哈希表实现的无序集合,元素唯一,按照哈希值分组,查找复杂度为 O(1)。
  • unordered_multiset:基于哈希表实现的无序集合,元素可重复,按照哈希值分组,查找复杂度为 O(1)。
  • unordered_map:基于哈希表实现的关联数组,键值对存储,自动扩容和重组,查找复杂度为 O(1)。
  • unordered_multimap:基于哈希表实现的关联数组,键可以重复,键值对按照插入顺序存储,查找复杂度为 O(1)。

容器适配器

  • stack 是基于 deque 或 vector 或 list 实现的栈容器适配器,支持后进先出(LIFO)的元素存取。由于栈的特殊性,只允许从栈顶进行插入和删除操作,因此其接口与 vector 容器类似,只提供了 push、pop、top 等操作。
  • queue 是基于 deque 或 list 实现的队列容器适配器,支持先进先出(FIFO)的元素存取。队列要求从队尾插入元素,从队头删除元素。因此,其接口与 deque 容器类似,只提供了 push、pop、front 和 back 等操作。
  • priority_queue 是基于 vector 实现的堆容器适配器,支持自动排序和高效的插入、删除操作。堆排序的实现需要维护一个二叉堆,而 C++ STL 中提供了一个优先队列容器适配器,可以方便地实现优先队列功能。该容器适配器类似于队列,但是每次插入元素时会自动调整堆得顺序,使得队首元素始终是最大值(或最小值)。

组件

  • pair 是用来存储一对值的容器适配器,可以用来定义关联数组、映射表等数据结构。例如可以使用 pair 存储一个字符串和一个整数,一个日期和一个时间等。pair 可以使用 STL 中的算法和容器进行操作,例如 vector、map、set 等。
  • heap 是堆排序算法的一部分,它并不是一种容器或容器适配器。STL 中提供了 make_heap、push_heap 和 pop_heap 等函数,用于对容器中的元素进行堆排序。make_heap 函数将容器转换为堆,push_heap 函数在堆中插入新元素,pop_heap 函数删除堆顶元素并重新调整堆的结构。使用 heap 可以快速地对序列排序和查找最值等操作。

迭代器

C++ STL 中的迭代器可以被用于遍历容器中的元素,它是一种抽象概念,可以遍历各种STL容器。以下是 C++ STL 中所有的迭代器:

  • 输入迭代器(Input iterator):输入迭代器只支持单向移动,可以读取容器中的元素。例如,istream_iterator 就是一种输入迭代器,用于从文件或输入流中读取数据。

  • 输出迭代器(Output iterator):输出迭代器也只支持单向移动,可以将数据写入容器中。例如,ostream_iterator 就是一种输出迭代器,可以将数据写入文件或输出流中。

  • 前向迭代器(Forward iterator):前向迭代器支持单向移动,可以读取和修改容器中的元素,但不能反复遍历同一个元素。例如,list 和 forward_list 都支持前向迭代器。

  • 双向迭代器(Bidirectional iterator):双向迭代器支持双向移动,可以在容器中向前或向后遍历元素。例如,deque、set、multiset、map、multimap 等支持双向迭代器。

  • 随机访问迭代器(Random access iterator):随机访问迭代器支持任意方向上的移动,可以直接访问容器中的任意元素,支持常数时间的加、减和随机访问操作。例如,vector、string 和 array 都支持随机访问迭代器。

  • ⭐除了以上五种迭代器,C++ STL 还提供了一些其他类型的迭代器,例如反向迭代器(reverse iterator)、插入迭代器(insert iterator)等。

总的来说,C++ STL 中的迭代器是用于遍历容器中元素的标准化接口,它们可以方便地在各种容器上进行操作,并且提供了多种不同的遍历方式。

算法(函数)

常用数学函数

C++ STL 中的数学函数主要包括以下几个:

  1. 算术操作(Arithmetic operations):
  • plus:加法运算。
  • minus:减法运算。
  • multiplies:乘法运算。
  • divides:除法运算。
  • modulus:求模运算。
    这些算法函数可以对容器中的元素进行逐个的算术操作,例如求和、计算平均数等。
  1. 一般数学函数(General mathematical functions):
  • abs:计算绝对值。
  • sqrt:计算平方根。
  • pow:计算幂。
  • exp:计算指数函数。
  • log:计算自然对数。
  • log10:计算以 10 为底的对数。
  • ceil:向上取整。
  • floor:向下取整。
  • round:四舍五入。
  • max:返回两个数中的最大值。
  • min:返回两个数中的最小值。
    这些函数可以帮助程序员进行各种数学计算,例如计算某个数的平方根、计算某个数的幂、计算某个数的指数函数值等。

除此之外,STL 还提供了一些其他的数学函数,例如:

  1. 随机数生成器(Random number generators):
  • rand:生成伪随机数。
  • srand:设置随机数生成器的种子,一般使用系统时间作为种子。
    这些函数可以帮助程序员生成随机数,用于实现各种随机算法。

总的来说,C++ STL 中提供了许多数学函数和算法函数,它们可以大大简化程序员的开发工作,提高代码的可维护性和可读性。

常用的非数学函数

  • std::find():在给定的容器中查找元素,并返回指向第一个匹配元素的迭代器。如果未找到匹配元素,则返回尾迭代器。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
auto it = std::find(vec.begin(), vec.end(), 3);
if (it != vec.end()) {
    std::cout << "Found: " << *it << '\n';
}
  • std::count():计算给定值在容器中出现的次数。例如:
std::vector<int> vec {1, 2, 3, 4, 5, 3};
int count = std::count(vec.begin(), vec.end(), 3);
std::cout << "Count of 3: " << count << '\n';
  • std::copy():从一个容器(或者迭代器区间)复制数据到另一个容器(或者位置)。例如:
std::vector<int> src {1, 2, 3, 4, 5};
std::vector<int> dest(5);  // 目标容器需要预分配空间
std::copy(src.begin(), src.end(), dest.begin());
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::transform():对一个范围内的元素进行某种操作,并将结果放入目标容器中。例如,下面的代码将 vec 容器中的元素都加倍并存储到 dest 容器中:
std::vector<int> vec {1, 2, 3, 4, 5};
std::vector<int> dest(vec.size());
std::transform(vec.begin(), vec.end(), dest.begin(),
               [](int i) { return i * 2; });
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::sort():对容器中的元素进行排序,支持自定义比较函数。例如:
std::vector<int> vec {5, 2, 4, 1, 3};
std::sort(vec.begin(), vec.end());  // 默认从小到大排序
for (auto i : vec) {
    std::cout << i << ' ';
}

其他

⭐ 关键字auto(不属于STL)

可以和 STL 容器、算法、迭代器等紧密结合使用,可以方便地推导出容器中元素、算法返回值、迭代器指向的类型等信息。例如,在使用 STL 容器时,可以使用 auto 定义迭代器类型:

std::vector<int> vec {1, 2, 3, 4, 5};
for(auto it = vec.begin(); it != vec.end(); ++it) {
    // 使用 auto 推导出迭代器类型为 decltype(vec)::iterator 
    std::cout << *it << " ";
}

在 C++11 之前,如果要使用 STL 容器的迭代器,需要编写冗长的迭代器类型名称,例如:

std::vector<int> vec {1, 2, 3, 4, 5};
for(std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it) {
    // 使用 std::vector<int>::const_iterator 进行迭代
    std::cout << *it << " ";
}

通过使用 auto 关键字,可以让代码更简洁、易读,降低出错的概率。因此,虽然 auto 不属于 STL,但在使用 STL 时经常会和 auto 关键字一起使用。

一些常见用法

int a[5] = {1, 3, 5, 7, 9};
for (auto x : a) cout << x;
cout << endl;

vector<int>v(7, 6);
for (auto x : v) cout << x;
cout << endl;

string s = "acdb";
for (auto x : s) cout << x;
cout << endl;

char c[5] = {'b', 'a', 'd', 'c'};
for (auto x : c) cout << x;

//	输出
13579
6666666
acdb
badc





算法(函数)

常用数学函数

C++ STL 中的数学函数主要包括以下几个:

  1. 算术操作(Arithmetic operations):
  • plus:加法运算。
  • minus:减法运算。
  • multiplies:乘法运算。
  • divides:除法运算。
  • modulus:求模运算。
    这些算法函数可以对容器中的元素进行逐个的算术操作,例如求和、计算平均数等。
  1. 一般数学函数(General mathematical functions):
  • abs:计算绝对值。
  • sqrt:计算平方根。
  • pow:计算幂。
  • exp:计算指数函数。
  • log:计算自然对数。
  • log10:计算以 10 为底的对数。
  • ceil:向上取整。
  • floor:向下取整。
  • round:四舍五入。
  • max:返回两个数中的最大值。
  • min:返回两个数中的最小值。
    这些函数可以帮助程序员进行各种数学计算,例如计算某个数的平方根、计算某个数的幂、计算某个数的指数函数值等。

除此之外,STL 还提供了一些其他的数学函数,例如:

  1. 随机数生成器(Random number generators):
  • rand:生成伪随机数。
  • srand:设置随机数生成器的种子,一般使用系统时间作为种子。
    这些函数可以帮助程序员生成随机数,用于实现各种随机算法。

总的来说,C++ STL 中提供了许多数学函数和算法函数,它们可以大大简化程序员的开发工作,提高代码的可维护性和可读性。

常用的非数学函数

  • std::find():在给定的容器中查找元素,并返回指向第一个匹配元素的迭代器。如果未找到匹配元素,则返回尾迭代器。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
auto it = std::find(vec.begin(), vec.end(), 3);
if (it != vec.end()) {
    std::cout << "Found: " << *it << '\n';
}
  • std::find_if():在给定范围内查找满足某个条件的第一个元素,并返回该元素的迭代器。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
auto it = std::find_if(vec.begin(), vec.end(), [](int i) {
    return i % 2 == 0;  // 查找第一个偶数
});
if (it != vec.end()) {
    std::cout << "found: " << *it << '\n';
}
  • std::count():计算给定值在容器中出现的次数。例如:
std::vector<int> vec {1, 2, 3, 4, 5, 3};
int count = std::count(vec.begin(), vec.end(), 3);
std::cout << "Count of 3: " << count << '\n';
  • std::copy():从一个容器(或者迭代器区间)复制数据到另一个容器(或者位置)。例如:
std::vector<int> src {1, 2, 3, 4, 5};
std::vector<int> dest(5);  // 目标容器需要预分配空间
std::copy(src.begin(), src.end(), dest.begin());
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::sort():对容器中的元素进行排序,支持自定义比较函数。例如:
std::vector<int> vec {5, 2, 4, 1, 3};
std::sort(vec.begin(), vec.end());  // 默认从小到大排序
for (auto i : vec) {
    std::cout << i << ' ';
}


bool cmp(int a,int b) {return a>b;}  // 自定义比较函数,从大到小排序
std::vector<int> vec {5, 2, 4, 1, 3};
std::sort(vec.begin(), vec.end(), cmp);
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::nth_element():对给定范围内的元素进行部分排序,使得指定位置的元素在排序后处于正确位置。在线性时间内查找出无序数组中第 k 个元素,并将其放置于正确的位置上,左侧所有元素都比该元素小,右侧所有元素都比该元素大。其中,iter_nth 表示待查找的区间的起始位置,iter_nth + k 表示待查找的区间的终止位置,comp 为可选参数,指定自定义比较函数。例如:
std::vector<int> vec {3, 1, 4, 2, 5};
std::nth_element(vec.begin(), vec.begin() + 2, vec.end());  // 将第三个元素放到正确的位置
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::accumulate():对给定范围内的元素进行累加操作,计算区间中一系列值的和,并返回总和。支持自定义起始值和二元操作函数。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0);  // 从 0 开始累加 
std::cout << "Sum: " << sum << '\n';
  • std::fill():将指定值赋给容器中的所有元素,可以使用 任何类型的值 来填充容器。例如:
std::vector<int> vec(5);
std::fill(vec.begin(), vec.end(), 42);
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::memset():对一段内存块进行填充,按 字节 进行填充二进制数据,每个字节都会被赋予相同的值。例如:
std::vector<int> v {1, 2, 3, 4, 5};
std::fill(v.begin(), v.end(), 0);
for (auto i : v) {
    std::cout << i << ' ';
}
  • std::min_element() 和 std::max_element():分别返回给定容器中最小和最大元素的迭代器。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
auto min_it = std::min_element(vec.begin(), vec.end());
auto max_it = std::max_element(vec.begin(), vec.end());
std::cout << "Min: " << *min_it << ", Max: " << *max_it << '\n';
  • std::lexicographical_compare():比较两个容器的字典序大小。例如:
std::vector<int> vec1 {1, 2, 3};
std::vector<int> vec2 {3, 2, 1};
bool result = std::lexicographical_compare(vec1.begin(), vec1.end(),
                                           vec2.begin(), vec2.end());
std::cout << "vec1 < vec2: " << std::boolalpha << result << '\n';
  • std::merge():将两个已排序的容器合并成一个已排序的容器。例如:
std::vector<int> vec1 {1, 3, 5};
std::vector<int> vec2 {2, 4, 6};
std::vector<int> dest(vec1.size() + vec2.size());
std::merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), dest.begin());
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::reverse():将给定范围内的元素翻转。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
std::reverse(vec.begin(), vec.end());
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::reverse_copy():将给定范围内的元素复制到另一个容器中,并反转元素的顺序。例如:
std::vector<int> src {1, 2, 3, 4, 5};
std::vector<int> dest(src.size());
std::reverse_copy(src.begin(), src.end(), dest.begin());  // 反转元素顺序并复制到 dest 中
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::unique():对给定范围内的 相邻元素 执行去重操作,并返回指向去重后范围末尾的迭代器。使用建议先排序再去重。例如:
std::vector<int> vec {1, 2, 2, 3, 3, 3, 4, 5, 5};
auto it = std::unique(vec.begin(), vec.end());
vec.erase(it, vec.end());  // 删除去重后的冗余元素
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::unique_copy():将给定范围内的元素复制到目标容器中,删除其中相邻重复的元素。例如:
std::vector<int> vec {1, 2, 2, 3, 3, 3, 4, 5, 5};
std::vector<int> dest(vec.size());
auto end_it = std::unique_copy(vec.begin(), vec.end(), dest.begin());
for (auto it = dest.begin(); it != end_it; ++it) {
    std::cout << *it << ' ';
}
  • std::binary_search():使用二分查找算法在给定范围内查找指定元素,并返回是否查找成功。注意,该函数要求范围内元素已经按升序排序。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
bool result = std::binary_search(vec.begin(), vec.end(), 3);  // 在 vec 中查找元素 3
std::cout << "found: " << std::boolalpha << result << '\n';
  • std::next_permutation():给定一个排列,生成下一个排列。如果当前排列为最后一个,则返回 false。常用于全排列。例如:
std::vector<int> vec {1, 2, 3};
do {
    for (auto i : vec) {
        std::cout << i << ' ';
    }
    std::cout << '\n';
} while (std::next_permutation(vec.begin(), vec.end()));  // 输出所有排列
  • std::partition():以给定谓词为分界点,将容器中元素按照满足或不满足谓词的条件分成两部分,并返回分界迭代器。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
auto it = std::partition(vec.begin(), vec.end(), [](int i) {
    return i % 2 == 0;  // 将偶数和奇数分开
});
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::stable_partition():与 std::partition() 功能类似,但保持相对顺序不变。例如:
std::vector<int> vec {1, 2, 3, 4, 5, 6};
std::stable_partition(vec.begin(), vec.end(), [](int i) {
    return i % 2 == 0;  // 将偶数和奇数分开,但保持相对顺序
});
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::partial_sum():对给定范围内的元素进行部分求和操作,并将结果(当前元素及前面所有元素之和)放入目标容器中。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
std::vector<int> dest(vec.size());
std::partial_sum(vec.begin(), vec.end(), dest.begin());
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::iota():对给定范围内的元素递增赋值。例如:
std::vector<int> vec(5);
std::iota(vec.begin(), vec.end(), 1);
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::rotate():将给定范围内的元素旋转指定距离,使得指定位置的元素处于范围末尾。相当于提取出前几位元素拼接到最后。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
std::rotate(vec.begin(), vec.begin() + 2, vec.end());  // 将前两个元素移动到最后
for (auto i : vec) {
    std::cout << i << ' ';
}
  • std::adjacent_difference():对给定范围内的相邻元素执行差分操作,并将结果放入目标容器中。例如:
std::vector<int> vec {1, 2, 3, 4, 5};
std::vector<int> dest(vec.size());
std::adjacent_difference(vec.begin(), vec.end(), dest.begin());
for (auto i : dest) {
    std::cout << i << ' ';
}
  • std::inner_product():对两个范围内的元素进行内积计算,并返回结果。例如:
std::vector<int> vec1 {1, 2, 3};
std::vector<int> vec2 {4, 5, 6};
int result = std::inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0);  // 对 vec1 和 vec2 中元素进行内积计算
std::cout << "inner product: " << result << '\n';
  • std::clamp():将给定值限制在指定范围内,超出部分截断。例如:
int value = 10;
int result = std::clamp(value, 1, 5);  // 将 value 限制在 [1, 5] 范围内
std::cout << "result: " << result << '\n';

下面的很乱很乱,还没整理好

下面的很乱很乱,还没整理好

下面的很乱很乱,还没整理好

下面的很乱很乱,还没整理好

常用函数

字符串处理(用的很多)

  • find() 查找字符串,找不到返回-1
  • str.replace(pos,len,str)
    替换,用str替换指定字符串从起始位置pos开始长度为len的字符
str=str.replace(str.find("a"),2,"#");  //从第一个a位置开始的两个字符替换成#
str=str.replace(str.begin(),str.begin()+5,"#"); //用#替换从begin位置开始的5个字符
  • substr()
    截取字符串,返回下标从a到b的字符串
c=s.substr(a,b)//截取s的下标a开始的b的字符(不足或b不写则到结尾)并赋值给c

string s = "asdfg";
cout << s.substr(1,2) << endl;//此时会输出sd
  • 字符串对比
    compare(), strcmp()
string s1="asd", s2="asd";
s1.compare(s2);
/*相等返回0, 大于返回1, 小于返回-1*/
char s1[10]="asd", s2[10]="zxc"
strcmp(s1, s2);
/*相等返回0*/
  • 字符串翻转
    reverse() 函数没有返回值
string str="asdf";
reverse(str.begin(),str.end());

获取字符串长度

string型:s.length(), s.size()
char型:strlen(s),sizeof(str)/sizeof(str[0]),s.length()

  • strlen()函数求出的字符串长度为有效长度,既不包含字符串末尾结束符 ‘\0’;
  • length()函数求出的字符串长度不包含字符串末尾结束符’\0’;
  • sizeof()操作符求出的长度包含字符串末尾的结束符 ‘\0’;
    当在函数内部使用sizeof()求解由函数的形参传入的字符数组的长度时,得到的结果为指针的长度,既对应变量的字节数,而不是字符串的长度,此处一定要小心。

获取字符/字符串

  • getline :可接收空格,适用string
    getline(cin,s) 取值一行,记得getchar()取回车
string str;
getline(cin,str);
  • getchar() :接受一个字符,可接收空格,回车,只适用于char,常用于吃回车
  • cin.get :可接收空格,只适用于char,获取指定数量字符
char ch[20];
cin.get(ch, 11);//获取10个字符
char ch1;
cin.get(ch1);//获取1个字符,相当于ch1 = cin.get()
  • cin.getline() :可接收空格,只适用于char,用法和cin.get()差不多,获取指定数量字符
char a[20];
cin.getline(a, 20);

char m[3][20];
for(int i=0;i<3;i++)
	cin.getline(m[i],20);
  • gets() : 接收一个字符串,可以接收空格,只适用于char
char ch[20];
gets(ch);

数组/容器 处理

  • lower_bound/upper_bound
    只能在有序数组或容器中操作!!!
(lower_bound(a,a+n,int num)-a):在数组a中找到第一个大于等于num的数字并返回其下标

int a[] = {1, 2, 3, 4, 5, 7, 8, 9};
printf("%d", lower_bound(a, a + 8, 6) - a);//-a不能少,因为是地址相减
输出5,a->a+8中第一个大于等于6的位置是5

(upper_bound(a,a+n,int num)-a):在数组a中找到第一个大于num的数字并返回其下标
  • sort()
    //快排,可自定义cmp函数,也可以用于结构体排序
bool compare(int a,int b){
	return a>b;//降序
}
sort(num,num+4,compare);
  • max_element(),min_element()
    这两个函数用来快速得到数组中的最大/小值和最大/小值下标
    min_element()和max_element()的应用方法相同
int num[6]={1,0,5,2,5,0};
cout << *max_element(num,num+6) << endl;
//则此时输出的是num数组的最大值5
cout << max_element(num,num+6)-num << endl;
//则此时输出的是num数组的最大值的下标2
  • unique
    去重函数
    注意:unique只是能对相邻元素去重
    用这个函数之前还需要使用sort()进行排序才行,更重要的是所谓的去重并没有将重复的内容删去,而是把他们都排在了最后面
unique(data,data+n)//将date数组去重,n是数组长度
  • swap
    交换
swap(a,b)//a和b进行交换
  • 翻转
    reverse() 函数没有返回值
int num[3]={ 1, 2, 3 };
reverse( num, num+3 );//3是数组长度

vector<int> v = { 1, 2, 3 };
reverse(v.begin(),v.end());

string str="asdf";
reverse(str.begin(),str.end());
  • find()
    在数组中查找某个值
    find 能查到就返回下标地址,找不到返回数组长度
    i 的位置=find(开始位置,结束位置+1,i )
int num[] = {1, 2, 3};
int *index;
index = find(num, num+3, 3);//index是查找到3的所在地址
cout << index-num << endl;//用3所在地址减去数组首元素地址就是3的下标

index = find(num, num+3, 5);//找不到返回数组长度所在地址
cout << index-num << endl;
/*这里输出数组长度3*/

数学思想

__gcd()
辗转相除(最大公因数、最小公倍数)

求最大公约数,调用万能头文件

int gc = __gcd(4,8);
//如果用不了参考
int gcd(int a,int b){
    if(b==0) return a;
    else
        return gcd(b,a%b);
}

最小公倍数

int lcm(int a,int b){
	return a/__gcd(a,b)*b;
}

STL

  • next_permutation()
    全排列这是在STL中的,注意要先将数组用sort排个升序
//int型数组:
sort(num,num+3);
int num[3] = {5,2,6};
	sort(num,num+3);
	//先使用sort排个序
	do{
		for(int i=0;i<3;i++)
			cout << num[i] << "  ";
		cout << endl;
	}while(next_permutation(num,num+3)); 

//string型: 
string s;
	cin >> s ;
	sort(s.begin(),s.end());
	//先使用sort排个序
	do{
		cout << s << endl;
	}while(next_permutation(s.begin(),s.end())); 

容器类

vector、stack、queue、map、pair、heap
向量(vector)、双端队列(deque)、链表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)

一些函数用法还没记全
循环时用 auto 或者 迭代器 iterator

vector

一种容器,类似动态数组,但它的size可以动态改变

vector在获取元素和对最后一个元素的操作效率上更高;但对于中间元素的操作,性能则相对较差。

vector<int>v

vector<int >b(a) //将a中的元素复制到b中

vector<int>a(100,6)//定义100个值为6的元素

vector<string>b(a.begin(),a.end()) //将动态数组a的元素值复制到b中

v.begin()//返回指向迭代器第一个元素的指针

v.end()//返回指向迭代器最后一个元素的指针

v.size()//返回当前vector使用数据量的大小

v.empty()//测试vector是否为空

v.front()//返回第一个元素的值

v.back()//返回最后一个元素的值

v.push_back(x)//在容器最后一个位置插入元素x

v.pop_back(x)//删除最后一个元素

//insert erase swap

v.clear()//清空

//Iterators迭代器

vector<int>::iterator iter1;
for (iter1 = v.begin(); iter1 != v.end(); ++iter1) {
        cout << ' ' << *iter1 << endl;   //[0,1,2,3,4,5,6,7,8,9]
}

queue

queue<int> q:建立一个队列q,其内部元素类型是int。

q.push(a):将元素a插入到队列q的末尾。

q.pop():删除队列q的队首元素。

q.front():查询q的队首元素。

q.back():查询q的队尾元素。

q.size():查询q的元素个数。

q.empty():查询q是否为空。

set

set<int>a;

a.insert()//往集合中添加元素,它的参数也是只有一个,就是你想要添加的元素,无返回值。

a.count()//查找出现在集合中的元素的个数,返回值要么是1要么是0
//因为集合的互异性,所以它的返回值要么是1要么是0。
//一般也可以用它来判断某个元素是否在该集合中。

a.begin()和a.end()
//是有返回值的,返回值分别是第一个指向该元素的迭代器和指向最后一个元素迭代器的下一个位置

a.erase()//函数是用来删除指定的元素,参数只有一个,并且是你想要删除的元素,无返回值

a.size()//得出集合中的元素个数。

a.empty()//判断该集合是否为空。 

a.clear()//清空集合中的元素。

stack

stack<int> S;	//定义一个存储整数类型的栈

top()//返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。

push(const T& obj)//将对象压入栈顶
//这是通过调用底层容器的 push_back() 函数完成的。

push(T&& obj)//以移动对象的方式将对象压入栈顶。
//这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。

pop()//弹出栈顶元素。

size()//返回栈中元素的个数。

empty()//在栈中没有元素的情况下返回 true。

emplace()//用传入的参数调用构造函数,在栈顶生成对象。

pair

//底层使用结构体实现,存储一对数据

pair<T1, T2> p1;

p1.first = 1;
 
p1.second = 2.5;
 
cout<<p1.first<<' '<<p1.second<<endl;

map

map<typename1, typename2> mp //typename1是键的类型,typename2是值的类型。

//map中的键是唯一的

map<char, int> mp; 
mp['c'] = 20;
cout << mp['c'];	//答案输出20

//map可以使用it->first来访问键,it->second来访问值

//map会以键从小到大的顺序自动排序

find()
map<char, int>::iterator it = mp.find('b');
cout << it->first << " " << it->second;

erase()
mp.erase(it)//it为需要删除的元素的迭代器
mp.erase(key)//key为要删除的映射的键
mp.erase(first, last)//其中,first为需要删除的区间的起始迭代器,last为需要删除的区间末尾迭代器的下一个地址,即为删除左闭右开的区间[first, last)

size()//获得map中映射的对数

clear()//清空map中的所有元素

unordered_map

unordered_map<string, int> umap; //定义

heap


完全二叉树,父节点均不小于/大于子节点

make_heap(v.begin(), v.end(), greater<int>());//生成一个小堆,第三个不加就默认最小堆,加greater<int>()则为最大堆

pop_heap(v.begin(), v.end(), greater<int>()); // 将堆的第零个元素与最后一个元素交换

v.pop_back(); // 删除最后位置的元素

list

使用双链表实现

猜你喜欢

转载自blog.csdn.net/weixin_45940369/article/details/131059386