C++ 算法函数

2025 年 8 月 29 日 | 阅读 20 分钟

在 C++ 中,标准模板库 (STL) 在 `` 头文件中提供了强大的底层函数集合。这些函数有助于对数组、向量、列表和其他容器等序列执行广泛的操作。算法函数是通用的,并且操作于迭代器,这使得它们可以跨多种容器类型重用。

算法类型

算法主要有两种类型。它们如下:

  1. 非修改算法
  2. 修改算法

现在,我们将逐一讨论这些算法。

非修改算法

在 C++ 中,非修改算法在不改变其值的情况下对元素序列进行操作。它们的主要用途是对各种元素执行查询、比较和检查。当目的是检索信息而不是更改容器的内容时,这些算法效果很好。常见示例包括 `find()`,它查找给定值,以及 `count()`,它计算特定元素出现的次数。

这些函数效率高,可确保数据完整性,并且是分析或验证 STL 容器(如向量、列表和数组)中元素的关键工具。

修改算法

在 C++ 中,修改算法是指修改或重新排列范围中元素的算法。这些算法会更改原始数据,而不是创建新容器。有几种修改算法,例如 `sort()`、`reverse()`、`rotate()`、`partition()`、`remove()` 等。这些算法通常用于高效的就地数据转换。

C++ 算法的成员函数

以下是 map 的所有成员函数列表

标准非修改序列算法

下表显示了 C++ 算法中使用的几种标准非修改序列操作。

函数描述
all_of此函数用于测试范围内所有元素的条件。
any_of此函数用于测试范围内某些或任何元素的条件
none_of此函数用于检查是否没有元素满足条件。
for_each该函数将操作应用于范围内的所有元素。
find该函数在范围内查找值。
find_if该函数在范围内查找元素。
find_if_not该函数以与上面相反的方式在范围内查找元素。
find_end此函数用于返回范围的最后一个元素。
find_first_of该函数查找满足条件且出现在第一个的元素。
adjacent_find该函数在范围内搜索查找相等且相邻的元素。
count该函数返回范围内某个值的计数。
count_if该函数返回满足条件的计数值。
mismatch该函数返回序列中第一个不匹配的值。
equal该函数用于检查两个范围是否所有元素都相等。
is_permutation该函数检查范围是否是某个其他范围的排列。
search该函数在范围内搜索子序列。
search_n该函数在范围内搜索元素的出现次数。

C++ 非修改序列操作示例

让我们举例说明 C++ 中的非修改序列操作。

示例

编译并运行

输出

All elements are even? false
Any element is odd? true
No negative elements? true
Elements: 2 4 6 8 10 3 4 6 8 10 
First occurrence of 6 found at index: 2
First element > 8 is: 10
First non-even element: 3
Last occurrence of {4, 6} starts at index: 6
First matching element from {3,7,9} is: 3
First pair of adjacent equal elements: 3 and 3
Count of 4s in data: 2
Count of elements > 5: 6
First mismatch: 3 vs 0
Are d1 and d2 equal? false
Is b a permutation of a? true
Subsequence {6,8} found at index: 2

修改序列操作

下表显示了 C++ 算法中使用的几种修改序列操作。

函数描述
副本该函数复制元素范围。
copy_n该函数复制范围的 n 个元素
copy_if如果满足某个条件,该函数将复制范围的元素。
copy_backward该函数按倒序复制元素
move该函数移动元素范围。
move_backward该函数按倒序移动元素范围
swap该函数交换两个对象的值。
swap_ranges该函数交换两个范围的值。
iter_swap该函数交换引用下的两个迭代器的值。
transform该函数转换范围内的所有值。
replace该函数将范围内的值替换为特定值。
replace_if如果满足某个条件,该函数将替换范围的值。
replace_copy该函数通过替换元素来复制值范围。
replace_copy_if如果满足某个条件,该函数通过替换元素来复制值范围。
fill该函数使用某个值填充范围内的值。
fill_n该函数填充序列中的值。
generate该函数用于生成范围的值。
generate_n该函数用于生成序列的值。
remove该函数从范围内删除值。
remove_if如果满足某个条件,该函数将删除范围的值。
remove_copy该函数通过删除它们来复制范围的值。
remove_copy_if如果满足某个条件,该函数通过删除它们来复制范围的值。
unique该函数识别范围内的唯一元素。
unique_copy该函数复制范围内的唯一元素。
反转该函数反转范围。
reverse_copy该函数通过反转值来复制范围。
rotate该函数将范围中的元素向左旋转。
rotate_copy该函数复制向左旋转的范围中的元素。
random_shuffle该函数随机打乱范围。
shuffle该函数借助生成器随机打乱范围。

C++ 修改序列操作示例

让我们举例说明 C++ 中的修改序列操作。

示例

编译并运行

输出

Copied vector: 1 2 3 4 5 6 7 8 9 10 
Even elements (copy_if): 2 4 6 8 10 
Transformed (doubled) vector: 2 4 6 8 10 12 14 16 18 20 
Replaced 5 with 99: 1 2 3 4 99 6 7 8 9 10 
Removed 3 from vector: 1 2 4 5 6 7 8 9 10 
After unique(): 1 2 3 4 
Reversed vector: 10 9 8 7 6 5 4 3 2 1 
Rotated vector (left by 3): 4 5 6 7 8 9 10 1 2 3 
After swap_ranges(), swapped1: 2 4 6 8 10 12 14 16 18 20 
After swap_ranges(), swapped2: 1 2 3 4 5 6 7 8 9 10 
Shuffled vector: 6 9 1 7 4 3 5 8 2 10

分区

下表显示了 C++ 算法中使用的几种分区操作。

函数描述
is_partitioned该函数用于推断范围是否已分区。
partition该函数用于分区范围。
stable_partition该函数将范围分成两个稳定的部分。
partition_copy该函数在分区后复制范围。
partition_point该函数返回范围的分区点。

C++ 分区操作示例

让我们举例说明 C++ 中的分区操作。

示例

编译并运行

输出

Is the data partitioned (evens first)? false
After partition (evens first): 8 2 6 4 5 3 7 1 
After stable_partition (evens first, order preserved): 2 4 6 8 1 3 5 7 
Partitioned copy - evens: 8 2 6 4 
Partitioned copy - odds: 5 3 7 1 
Partition point index: 4

排序

下表显示了 C++ 算法中使用的几种排序操作。

函数描述
排序该函数对范围内的所有元素进行排序。
stable_sort该函数对范围内的元素进行排序,同时保持相等元素的相对顺序。
partial_sort该函数对范围的元素进行部分排序。
partial_sort_copy该函数在对范围进行排序后复制其元素。
is_sorted该函数检查范围是否已排序。
is_sorted_until该函数检查范围在哪个元素之前是已排序的。
nth_element该函数对范围内的元素进行排序。

C++ 排序操作示例

让我们举例说明 C++ 中的排序函数。

示例

编译并运行

输出

Sorted vector: 1 2 3 4 5 6 7 8 9 
Stable sorted vector of pairs: (1,b) (2,d) (3,a) (3,c) 
Partially sorted (first 5 smallest): 1 2 3 4 5 9 8 7 6 
Partial sort copy (5 smallest): 1 2 3 4 5 
Is the sorted vector actually sorted? true
is_sorted_until found unsorted at position: 4
After nth_element (5th smallest in correct place): 3 2 1 4 5 7 6 9 8 
5th smallest element is: 5

二分搜索

下表显示了 C++ 算法中使用的几种二分查找操作。

函数描述
lower_bound返回范围的下界元素。
upper_bound返回范围的上界元素。
equal_range该函数返回相等元素的子范围。
binary_search该函数测试范围内的值是否存在于排序序列中。

C++ 二分查找操作示例

让我们举例说明 C++ 中的二分查找操作。

示例

编译并运行

输出

Sorted data: 1 3 3 3 5 7 9 11 
Is value 3 present? true
Lower bound of 3 is at index: 1, value: 3
Upper bound of 3 is at index: 4, value: 5
Equal range of 3 is from index 1 to 4
Elements in equal range: 3 3 3

合并

下表显示了 C++ 算法中使用的几种合并操作。

合并

函数描述
merge该函数合并两个已排序的范围。
inplace_merge该函数合并两个相邻的已排序范围。
includes该函数搜索已排序范围是否包含另一个范围。
set_union该函数返回两个已排序范围的并集。
set_intersection该函数返回两个已排序范围的交集。
set_difference该函数返回两个已排序范围的差集。
set_symmetric_difference该函数返回两个已排序范围的对称差集。

C++ 合并操作示例

让我们举例说明 C++ 中的合并操作。

示例

编译并运行

输出

Merged A and B: 1 2 3 3 5 6 7 8 
After inplace_merge: 1 2 3 4 5 6 7 
Does superset include subset? true
Set union: 1 2 3 5 6 7 8 
Set intersection: 3 
Set difference (A - B): 1 5 7 
Set symmetric difference: 1 2 5 6 7 8

下表显示了 C++ 算法中使用的几种堆操作。

函数描述
push_heap该函数将新元素推入堆。
pop_heap该函数从堆中弹出新元素。
make_heap该函数用于创建堆。
sort_heap该函数对堆进行排序。
is_heap该函数检查范围是否为堆。
is_heap_until该函数检查范围在哪个位置是堆。

C++ 堆操作示例

让我们举例说明 C++ 中的堆操作。

示例

编译并运行

输出

Heap after make_heap: 30 20 10 5 15 
Heap after push_heap(25): 30 20 25 5 15 10 
Popped element: 30
Heap after pop_heap: 25 20 10 5 15 
Is the vector a heap? true
is_heap_until fails at index: 6
Heap after sort_heap (sorted array): 5 10 15 20 25

最小值/最大值

下表显示了 C++ 算法中使用的几种最小值/最大值操作。

函数描述
min返回范围中的最小元素。
max返回范围中的最大元素。
minmax返回范围中的最小和最大元素。
min_element返回范围中的最小元素。
max_element返回范围中的最大元素。
minmax_element返回范围中的最小和最大元素。

C++ 最小值/最大值操作示例

让我们举例说明 C++ 中的最小值/最大值操作。

示例

编译并运行

输出

min(10, 20): 10
max(10, 20): 20
minmax(10, 20): (10, 20)
Minimum element in vector: 9 at index 7
Maximum element in vector: 89 at index 5
Minmax in vector: min = 9, max = 89

其他函数

下表显示了 C++ 算法中有用的几种其他操作。

函数描述
lexicographical_comapre该函数执行字典序小于比较。
next_permutation该函数用于将范围转换为下一个排列。
prev_permutation该函数用于将范围转换为上一个排列。

C++ 算法函数的关键特性

C++ 算法函数有几个关键特性。一些主要特性如下:

  • 通用且基于模板:C++ 算法函数是基于模板的,这允许它们在不重写的情况下与各种数据类型和容器类型(如 vector、list 和 array)一起工作。
  • 修改和非修改类别:算法分为非修改(如 find、count 和 for_each)和修改(如 copy、replace 和 transform),取决于它们是否更改输入数据。
  • 支持自定义条件:许多特定函数(例如 find_if、count_if)用于定义谓词函数或 lambda 表达式,以增加自定义逻辑。
  • 高效且优化:STL 算法针对性能进行了优化,通常提供保证的时间复杂度(例如,sort 使用混合排序算法,复杂度为 O(n log n))。
  • 不调整容器大小:算法容器不管理大小或内存。

结论

总之,C++ 算法函数是通过标准模板库 (STL) 中的头文件提供的高效且富有表现力的编程的必备工具集。它们抽象了低级迭代逻辑,并为搜索、排序、修改、比较和转换数据等任务提供了干净、定制化的操作。

C++ 算法常见问题解答

1) C++ 中 `` 头文件的目的是什么?

在 C++ 中,`` 头文件提供了一系列预定义的函数,用于排序、搜索、计数和修改等操作。这些函数通过可重用逻辑替换手动编码,从而简化了代码。它们使用迭代器与容器广泛协作。它提高了 C++ 编程的可读性、效率和抽象性。

2) C++ 算法函数是否适用于所有类型的容器?

是的,算法函数操作于迭代器,而不是直接操作容器,因此它们可以与任何支持迭代器的 STL 容器一起使用,例如向量、列表,甚至是原始数组。这使得任务非常灵活。唯一的限制是某些算法需要特定的迭代器类型(例如,sort 需要随机访问迭代器)。

3) `std::sort()` 和 `std::stable_sort()` 之间有什么区别?

在 C++ 中,`std::sort()` 函数快速地对元素进行排序和重新排列,但不保留相等元素的原始顺序。另一方面,`std::stable_sort()` 在其原始相对位置上保持相等元素,这使得在有意义时顺序非常合适。虽然 `sort` 更高效,但 `stable_sort` 可确保在多级排序场景下的稳定性。

4) 算法函数如何通过谓词或 lambda 支持自定义逻辑?

许多算法接受一个自定义参数,称为谓词,它可以是函数指针、函数对象或 lambda 表达式。这允许函数在操作(如过滤、排序和搜索)期间应用用户定义的参数。Lambda 表达式被广泛用于编写简洁的内联逻辑。它使得 C++ 中的编程风格更具表现力和函数式。

5) 算法函数是否比手动循环更有效,为什么?

是的,算法函数通常比手动编写的循环更通用且更可靠。它们是 STL 的一部分,并受益于多年的测试和性能调优。它们使代码更易于理解,并且不易出错。开发人员不是专注于如何迭代,而是专注于要实现什么,从而使代码更具声明性。