STL 算法分类:
类别 | 常见算法 | 作用 |
---|---|---|
排序 | sort 、stable_sort 、partial_sort 、nth_element 等 | 排序 |
搜索 | find 、find_if 、count 、count_if 、binary_search 等 | 查找元素 |
修改 | copy 、replace 、replace_if 、swap 、fill 等 | 修改容器内容 |
删除 | remove 、remove_if 、unique 等 | 删除元素 |
归约 | for_each 、accumulate 等 | 处理数据 |
合并 | merge 、set_union 、set_intersection 等 | 处理有序序列 |
排列组合 | next_permutation 、prev_permutation 等 | 生成排列 |
堆操作 | push_heap 、pop_heap 、make_heap 、sort_heap 等 | 处理堆 |
一、STL 合并算法
STL 中的合并算法(Merge Algorithms)用于将两个有序的序列(通常是容器中的元素)合并成一个新的有序序列。
这些算法包括 merge
和 inplace_merge
等。
算法名称 | 功能描述 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|---|
merge | 合并两个有序范围并返回一个新的有序范围 | O(n + m) | O(n + m) | 合并两个有序序列并返回合并结果 |
inplace_merge | 合并两个相邻的有序范围,原地操作 | O(n) | O(1) | 合并相邻的有序范围,在原地进行合并 |
set_union | 计算两个有序范围的并集,去除重复元素 | O(n + m) | O(n + m) | 计算两个有序序列的并集 |
set_intersection | 计算两个有序范围的交集 | O(n + m) | O(min(n, m)) | 计算两个有序序列的交集 |
set_difference | 计算两个有序范围的差集,返回第一个范围独有的元素 | O(n + m) | O(n) | 计算两个有序序列的差集 |
(1)merge
- 功能:将两个有序的容器(或范围)合并成一个新的有序容器。该算法返回一个指向结果容器末尾的迭代器。
- 时间复杂度:O(n + m),其中
n
和m
是两个输入序列的长度。 - 空间复杂度:O(n + m),需要额外的存储空间来存储合并结果。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // merge
int main() {
vector<int> vec1 = { 1, 3, 5, 7 };
vector<int> vec2 = { 2, 4, 6, 8 };
vector<int> result(vec1.size() + vec2.size());
// 合并 vec1 和 vec2,结果存储在 result 中
merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());
cout << "Merged result: ";
for (int num : result)
{
cout << num << " "; // 输出:1 2 3 4 5 6 7 8
}
cout << endl;
system("pause");
return 0;
}
注意:
merge
用于合并两个有序范围(容器、数组等),并将结果保存到第三个容器中。
(2)inplace_merge
- 功能:将两个相邻的有序范围合并成一个有序范围,而不需要额外的存储空间。
该算法要求容器中这两个有序范围是连续的,并且只会在原地操作。 - 时间复杂度:O(n),其中
n
是这两个范围元素的总数。 - 空间复杂度:O(1),原地操作。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // inplace_merge
int main() {
vector<int> vec = { 1, 3, 5, 7, 2, 4, 6, 8 };
// 将 vec 中前四个元素和后四个元素合并
inplace_merge(vec.begin(), vec.begin() + 4, vec.end());
cout << "Inplace merged result: ";
for (int num : vec)
{
cout << num << " "; // 输出:1 2 3 4 5 6 7 8
}
cout << endl;
system("pause");
return 0;
}
注意:
inplace_merge
用于在原地合并两个相邻的有序范围,通常适用于某些排序算法(如归并排序)。
(3)set_union
- 功能:计算两个有序范围的并集,去除重复元素,并将结果存储在目标范围中。
- 时间复杂度:O(n + m),其中
n
和m
是两个输入范围的长度。 - 空间复杂度:O(n + m),需要额外的存储空间来存储合并结果。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // set_union
int main() {
vector<int> vec1 = { 1, 3, 5, 7 };
vector<int> vec2 = { 2, 4, 6, 8 };
vector<int> result(vec1.size() + vec2.size());
// 计算并集
auto it = set_union(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());
cout << "并集结果: ";
for (auto i = result.begin(); i != it; ++i)
{
cout << *i << " "; // 输出:1 2 3 4 5 6 7 8
}
cout << endl;
system("pause");
return 0;
}
注意:
set_union
适用于,当需要计算两个有序序列的并集时。
(4)set_intersection
- 功能:计算两个有序范围的交集,并将结果存储在目标范围中。交集中的元素是两个范围都包含的元素。
- 时间复杂度:O(n + m),其中
n
和m
是两个输入范围的长度。 - 空间复杂度:O(min(n, m)),需要额外的存储空间来存储合并结果。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // set_intersection
int main() {
vector<int> vec1 = { 1, 3, 5, 7 };
vector<int> vec2 = { 3, 5, 7, 9 };
vector<int> result(min(vec1.size(), vec2.size()));
// 计算交集
auto it = set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());
cout << "交集结果: ";
for (auto i = result.begin(); i != it; ++i)
{
cout << *i << " "; // 输出:3 5 7
}
cout << endl;
system("pause");
return 0;
}
注意:
set_intersection
适用于,当需要计算两个有序序列的交集时。
(5)set_difference
- 功能:计算两个有序范围的差集,返回在第一个范围中但不在第二个范围中的元素。
- 时间复杂度:O(n + m),其中
n
和m
是两个输入范围的长度。 - 空间复杂度:O(n),最多为第一个集合的长度。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // set_difference
int main() {
vector<int> vec1 = { 1, 3, 5, 7 };
vector<int> vec2 = { 3, 5, 7, 9 };
vector<int> result(vec1.size());
// 计算差集
auto it = set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), result.begin());
cout << "差集结果: ";
for (auto i = result.begin(); i != it; ++i)
{
cout << *i << " "; // 输出:1
}
cout << endl;
system("pause");
return 0;
}
注意:
set_difference
适用于,当需要计算两个有序序列的差集时。
二、STL 排列组合算法
STL 提供了一些用于生成排列和组合的算法,主要用于在容器中生成元素的排列或组合。
这些算法可以广泛应用于算法设计、组合数学以及其他场景中。
算法名称 | 功能描述 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|---|
next_permutation | 生成下一个字典序排列 | O(n) | O(1) | 用于生成所有排列,直到没有更多的排列为止 |
prev_permutation | 生成上一个字典序排列 | O(n) | O(1) | 用于生成所有排列的逆向排列 |
shuffle | 随机打乱元素顺序 | O(n) | O(1) | 用于随机排列容器元素 |
(1)next_permutation
- 功能:生成容器元素的下一个字典序排列。返回值表示是否成功生成下一个排列。
- 时间复杂度:O(n),其中
n
是容器中的元素数量。 - 空间复杂度:O(1),原地操作。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // next_permutation
int main() {
vector<int> vec = { 1, 2, 3 };
do
{
for (int i : vec)
{
cout << i << " ";
}
cout << endl;
} while (next_permutation(vec.begin(), vec.end()));
system("pause");
return 0;
}
注意:
next_permutation
用于生成元素的所有排列(字典序),直到没有更多的排列为止。
(2)prev_permutation
- 功能:生成容器元素的上一个字典序排列。返回值表示是否成功生成上一个排列。
- 时间复杂度:O(n),其中
n
是容器中的元素数量。 - 空间复杂度:O(1),原地操作。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // prev_permutation
int main() {
vector<int> vec = { 3, 2, 1 };
do
{
for (int i : vec)
{
cout << i << " ";
}
cout << endl;
} while (prev_permutation(vec.begin(), vec.end()));
system("pause");
return 0;
}
注意:
prev_permutation
用于从当前排列开始生成之前的排列。
(3)shuffle
- 功能:用于打乱容器元素的顺序。通过随机数生成器控制打乱的顺序,产生所有可能的排列之一。
- 时间复杂度:O(n),其中
n
是容器的大小。 - 空间复杂度:O(1),原地操作。
示例:
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm> // shuffle
#include <random>
int main() {
vector<int> vec = { 1, 2, 3, 4, 5 };
// 使用随机数生成器进行打乱
random_device rd;
mt19937 g(rd());
shuffle(vec.begin(), vec.end(), g);
cout << "打乱顺序后的容器: ";
for (int i : vec)
{
cout << i << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
shuffle
适用于,当需要随机排列容器元素时。mt19937
是基于梅森旋转算法(Mersenne Twister)的伪随机数生成器,属于高质量伪随机数算法的一种实现形式。