C++ STL泛型算法

泛型算法

<algorithm>定义了大约 80 个标准算法。
它们操作由一对迭代器定义的(输入)序列或单一迭代器定义的(输出)序列。
当对两个序列进行拷贝、比较操作时,第一个序列由一对迭代器[b,e)表示,但第二个序列只由一个迭代器b2表示,b2指出了序列的起始位置。
应当保证第二个序列包含足够多的的元素供算法使用。
大多数标准库算法返回迭代器;特别是,它们不返回结果的容器。
大多数标准库算法都有两个版本:

  • 一个“普通”版本使用常规操作(如<==)完成其任务。
  • 另一个版本接受关键操作参数
    在某些情况下,实参既可以解释为谓词,也可以解释为值。

不修改序列的算法

for_each()

最简单的算法是 for_each(),它简单地对序列中的每个元素执行指定操作。

	vector<int> v{ 2,4,6,8 };for_each( v.begin(), v.end(), [](int x) {cout << x << ' '; } );/* 输出 2 4 6 8 */
算法功能
f = for_each(b,e,f);[b,e)中的每个 x 执行f(x),返回 f

序列谓词

	vector<int> v{ 2,4,6,8 };auto flag = all_of(v.begin(), v.end(), [](int x) { return x > 0; });cout << flag << endl; // v 中的每个元素大于 0 ,输出 1

当一个序列谓词失败时,它不会告知我们是哪个元素导致了失败。

	vector<int> v{ 0,4,8,3 };auto flag = any_of(v.begin(), v.end(), [](int x) { return x > 5; });cout << flag << endl; //有元素大于 5 ,但不知道是哪个元素大于5
算法功能
all_of(b,e,f);[b,e)中所有 x 都满足f(x)吗?
any_of(b,e,f);[b,e)中某个 x 满足f(x)吗?
none_of(b,e,f);[b,e)中所有 x 都不满足f(x)吗?

count()

	vector<int> v{ 1,0,1,1,3 };cout << count(v.begin(), v.end(), 1) << endl; // 1 的数目为 3,输出 3
算法功能
x = count(b,e,v);x 为[b,e)中满足v==*p的元素,*p的数目
x = count_if(b,e,f);x 为[b,e)中满足f(*p)的元素,*p的数目

find()

find() 系列算法顺序搜索具有特定值或令谓词为真的元素。
谓词是一个可调用的表达式,其结果是一个能用作条件的值。
算法 find() 和 find_if() 都返回一个迭代器,分别指向匹配给定值和给定谓词的第一个元素。

	vector<char> v{ 'e','E','d','E','A'};auto p = find(v.begin(),v.end(),'E');cout << *p << endl;       //输出 Ecout << *(p + 1) << endl; //输出 d

算法 find_first_of() 查找序列中与另一个序列中元素相等的第一个元素。

	vector<char> v{ 'e','E','d','B','b' };array<char, 4> arr{ 'A','B','C','D' };auto p = find_first_of( v.begin(),v.end(),arr.begin(),arr.end() );cout << *p << endl; //输出 B
算法功能
p = find(b,e,v);p 指向[b,e)中第一个满足v==*p的元素
p = find_if(b,e,f);p 指向[b,e)中第一个满足f(*p)的元素
p = find_if_not(b,e,f);p 指向[b,e)中第一个满足!f(*p)的元素
p = find_first_of(b1,e1,b2,e2);p 指向[b1,e1)中第一个满足*p==*q的元素,其中 q 指向[b2,e2)中的某个元素
p = find_first_of(b1,e1,b2,e2,f);p 指向[b1,e1)中第一个满足f(*p,*q)的元素,其中 q 指向[b2,e2)中的某个元素
p = adjacent_find(b,e);p 指向[b,e)中第一个满足*p==*(p+1)的元素
p = adjacent_find(b,e,f);p 指向[b,e)中第一个满足f(*p,*(p+1))的元素
p = find_end(b1,e1,b2,e2);p 指向[b1,e1)中最后一个满足*p==*q的元素,其中 q 指向[b2,e2)中的某个元素
p = find_end(b1,e1,b2,e2,f);p 指向[b1,e1)中最后一个满足f(*p,*q)的元素,其中 q 指向[b2,e2)中的某个元素

equal()

算法 equal() 比较两个序列中的元素是否都相同。

	vector<char> v{ 'A','B','C','D','b' };array<char, 4> arr{ 'A','B','C','D' };auto b = equal( v.begin(),v.end() -1 ,arr.begin(),arr.end() );cout << b << endl; //输出 1 
算法功能
equal(b,e,b2);[b,e)[b2,b2+(e-b))中所有对应元素都满足v == v2
equal(b,e,b2,f);[b,e)[b2,b2+(e-b))中所有对应元素都满足f(v,v2)

mismatch()

算法 mismatch() 查找两个序列中第一对不匹配的元素,返回指向这两个元素的迭代器。
并没有参数指出第二个序列的末尾;算法假定第二个序列中至少包含与第一个序列一样多的元素。

	vector<char> v{ 'A','B','e','D' };array<char, 4> arr{ 'A','B','C','D' };auto p = mismatch( v.begin(),v.end() ,arr.begin() );cout << *(p.first) << endl;  //输出 ecout << *(p.second) << endl; //输出 C
算法功能
pair(p1,p2) = mismatch(b,e,b2);p1 指向[b,e)中第一个满足!(*p1 == *p2)的元素,p2 指向[b2,b2+(e-b))中对应的元素;若不存在这样的元素,则p1 == e
pair(p1,p2) = mismatch(b,e,b2,f);p1 指向[b,e)中第一个满足!f(*p1,*p2)的元素,p2 指向[b2,b2+(e-b))中对应的元素;若不存在这样的元素,则p1 == e

search()

算法 search() 和 search_n() 查找给定序列是否是另一个序列的子序列。

	vector<char> v{ 'E','A','B','C','D' };array<char, 3> arr{ 'A','B','C' } ;auto p = search(v.begin(), v.end(), arr.begin(), arr.end());cout << *p << endl; //输出 A;'A','B','C' 是 'E','A','B','C','D' 的子序列
算法功能
p = serach(b,e,b2,e2);p 指向[b,e)中第一个满足[p,p+(e2-b2))中等于[b2,e2)*p
p = serach(b,e,b2,e2,f);p 指向[b,e)中第一个满足[p,p+(e2-b2))中等于[b2,e2)*p,用 f 比较元素
p = serach_n(b,e,n,v);p 指向[b,e)中第一个满足[p,p+n)间所有元素的值均为 v 的位置
p = serach_n(b,e,n,v,f);p 指向[b,e)中第一个满足[p,p+n)间每个元素*q均满足f(*p,v)的位置

修改序列的算法

transform()

数据写入操作不能超出目标序列的末尾。

	array<char, 4> arr{ 'A','B','C','D' };vector<char> v{ 'E','A','B','C','Z'};transform(arr.begin(), arr.end(), v.begin(), [](char x) { return x += 32; });/* V 中的元素变为:a b c d Z */

输出和输入可能是同一个序列。

	vector<char> v{ 'E','A','B','C','Z'};transform(v.begin(), v.end(), v.begin(), [](char x) { return x += 32; });/* V 中的元素变为:e a b c z */
算法功能
p = transform(b,e,out,f);[b,e)中的每个元素*p1应用*q = f(*p1),结果写入[out,out + (e - b)中的对应元素*qp = out + (e - b)
p = transform(b,e,b2,out,f);[b,e)中的每个元素*p1及其在[b2,b2 + (e - b))中的对应元素*p2*应用*q = f(*p1,*p2),结果写入[out,out + (e - b)中的对应元素*qp = out + (e - b)

copy()

copy() 系列算法从一个序列拷贝至另一个序列。
为了读取一个序列,需要一对迭代器描述起始位置和结尾位置;为了向序列中写入数据,则只需一个迭代器。

	array<int,4> arr { 1,3,5,7 };vector<int> v{ 2,4,6,8 };auto p =copy( arr.begin(),arr.end(),v.begin() ); /* v 内的元素变为 1 3 5 7 */cout<< * (p-1) << endl; //输出 7;p = arr.end()

数据写入操作不能超出目标序列的末尾;但是,可以使用一个插入器按需增长目标序列。

	array<int,4> arr { 1,3,5,7 };vector<int> v{ 2,4,6,8 };copy(arr.begin(), arr.end(), back_inserter(v));/* v 内的元素变为 2 4 6 8 1 3 5 7 */

拷贝算法的目标序列不一定是一个容器,任何可用一个输出迭代器描述的东西都可以作为它的目标。

算法功能
p = copy(b,e,out);[b,e)中所有元素拷贝至 [out,p)p = out + (e - b)
p = copy_if(b,e,out,f);[b,e)中满足f(x)的元素 x 拷贝至[out,p)
p = copy_n(b,n,out);[b,b+n)间的前 n 个元素拷贝至 [out,p)p = out + n
p = copy_backward(b,e,out);[b,e)中的所有元素拷贝至 [out,p),从尾元素开始拷贝; p = out + (e - b)
p = move(b,e,out);[b,e)中所有元素移动至 [out,p)p = out + (e - b)
p = move_backward(b,e,out);[b,e)中的所有元素移动至 [out,p),从尾元素开始移动; p = out + (e - b)

unique()

算法 unique() 将不重复的元素移动到序列的头部,并返回指向不重复元素末尾位置的迭代器。

	vector<char> v{ 'A','A','C','E','E','B'};auto p = unique(v.begin(), v.end()); auto iter = v.begin();while (iter != p){cout << *iter++ << ' ';}cout << endl;/* 输出: A C E B */

为了从一个容器中删除重复元素,必须显示地收缩容器。

	vector<char> v{ 'A','A','C','E','E','B'};auto p = unique(v.begin(), v.end()); v.erase(p,v.end());
算法功能
p = unique(b,e);移动[b,e]中的一些元素,使得[b,p)中无连续重复元素
p = unique(b,e,f);移动[b,e]中的一些元素,使得[b,p)中无连续重复元素;“重复”由f(*p,*(p+1))判定
p = unique_copy(b,e,out);[b,e)中的元素拷贝至 [out,p);不拷贝连续重复元素
p = unique_copy(b,e,out,f);[b,e)中的元素拷贝至 [out,p);不拷贝连续重复元素;“重复”由f(*p,*(p+1))判定

remove()

算法 remove() "删除"序列末尾的元素;它是通过将元素移动到左侧来实现“删除”的。

	vector<char> v{ 'A','B','C','E','E','D' };auto p = remove(v.begin(), v.end(),'E');auto iter = v.begin();while (iter != p){cout << *iter++ << ' ';}cout << endl;/*输出:A B C D*/
算法功能
p = remove(b,e,v);[b,e]中删除值为 v 元素,使得[b,p)中的元素都满足!(*q == v)
p =remove(b,e,f);[b,e]中删除元素*q,使得[b,p)中的元素都满足!f(*q)
p = remove_copy(b,e,out,v);[b,e)中满足!(*q == v)的元素拷贝至 [out,p)
p = remove_copy_f(b,e,out,f);[b,e)中满足!f(*q)的元素拷贝至 [out,p)

raplace()

算法 raplace() 将新值赋予选定的元素。

	vector<char> v{ 'E','A','E','B','C','D' };replace(v.begin(), v.end(),'E','F'); // 将 E 替换为 F/* v 内的元素变为 F A F B C D */
算法功能
p = raplace(b,e,v,v2);[b,e)中满足*p == v的元素替换为 v2
p =raplace(b,e,f,v2);[b,e)中满足f(*p)的元素替换为 v2
p =raplace_copy(b,e,out,v,v2);[b,e)中的元素拷贝至 [out,p),其中满足*p == v的元素被替换为 v2
p = raplace_copy_f(b,e,out,f,v2);[b,e)中的元素拷贝至 [out,p),其中满足f(*p,v)的元素被替换为 v2

rotable() 、 random_shuffle() 和 partition()

算法 rotable() 、 random_shuffle() 和 partition() 提供了移动序列中元素的系统方法。
rotable()(以及洗牌和划分算法)是用 swap() 来移动元素的。

rotable()
	vector<char> v{ 'A','B','C','D','E' };auto p = rotate(v.begin(),v.begin()+2, v.end());/* v 内的元素变为 C D E A B */cout << *p << endl; // *p = A
算法功能
p = rotable(b,m,e);循环左移元素;将[b,e]看作一个环(首元素在尾元素之后);将*(b+i)移动到*( b + (i+(e-m))%(e-b) )*b移动到*mp = b+(e-m)
p = rotable_copy(b,m,e,out);[b,e]中的元素循环左移拷贝至[out,p)
random_shuffle()

默认情况下,random_shuffle() 用均匀分布随机数发生器洗牌序列。
即,它选择序列元素的一个排列,使得每种排列被选中的概率相等。

	vector<char> v{ 'A','D','C','B','E' };random_shuffle(v.begin(),v.end());/* v 内的元素变为 E D B C A */
算法功能
random_shuffle(b,e);洗牌[b,e]中的元素,使用默认随机数发生器
random_shuffle(b,e,f);洗牌[b,e]中的元素,使用随机数发生器 f
shuffle(b,e,f);洗牌[b,e]中的元素,使用均匀分布随机数发生器 f
partition()

划分算法基于某种划分标准将序列分为两部分。

	vector<char> v{ 'A','H','C','B','F' };auto p = partition(v.begin(), v.end(), [](char x) {return x < 'E'; });/* v 内的元素变为 A C B H F */cout << *p << endl; // *p = H
算法功能
p = partition(b,e,f);将满足f(*p1)的元素置于区间[b,p)内,将其它元素置于区间[p,e)
p = stable_partition(b,e,f);将满足f(*p1)的元素置于区间[b,p)内,将其它元素置于区间[p,e)内;保持相对顺序
pair(p1,p2) = partition_copy(b,e,out1,out2,f);[b,e)中满足f(*p)的元素拷贝到[out1,p1)内,将[b,e)中满足!f(*p)的元素拷贝到[out2,p2)
p = partition_point(b,e,f);[b,e),p 指向满足all_of(b,p,f)none_of(b,p,f)的位置
is_partitioned(b,e,f);[b,e)中满足f(*p)的元素都在满足!f(*p)的元素之前吗?

排列

例:打印序列 ABC 的所有排列组合:

	vector<char> v{ 'A','B','C' };bool x = true;while ( x ){x = next_permutation(v.begin(), v.end());for (auto i : v)cout << i << ' ';cout << endl;}/*  输出:A C BB A CB C AC A BC B AA B C*/

算法 next_permutation() 接受一个序列,将其变换为下一个排列。
"下一个"的定义基于这样一个假设:所有的排列组合已按字典序排序。
如果存在”下一个“排列组合,next_permutation() 返回 true;否则,它将序列变换为升序中排在第一位的排列组合(例中的 ABC),并返回 false;

算法功能
x = next_permutation(b,e);[b,e)变换为字典序上的下一个排列
x = next_permutation(b,e,f);[b,e)变换为字典序上的下一个排列;用 f 比较元素
x = prev_permutation(b,e);[b,e)变换为字典序上的前一个排列
x = prev_permutation(b,e,f);[b,e)变换为字典序上的前一个排列;用 f 比较元素
is_permutation(b,e,b2);[b2,b2+(e-b))[b,e)的一个排列?
is_permutation(b,e,f);[b2,b2+(e-b))[b,e)的一个排列?用 f(*q,*p) 比较元素

fill()

fill() 系列算法提供了向序列元素赋值和初始化元素的方法。
算法 fill() 反复用指定值进行赋值。

	vector<char> v{ 'A','H','C','B','F' };fill(v.begin(), v.end(), 'E');/* v 内的元素变为 E E E E E */

算法 generate() 则通过反复调用其函数实参得到的值进行赋值。

	vector<char> v{ 'A','H','C','B','F' };int i = 0;generate( v.begin(), v.end(), [&i] { ++i; return 'A'+ i; } );/* v 内的元素变为 B C D E F */

算法 uninitialized_fill() 或 uninitialized_copy() 的目标元素必须是内置类型或是未初始化的。

算法功能
fill(b,e,v);将 v 赋予[b,e)中的每一个元素
p = fill_n(b,n,v);将 v 赋予[b,b+n)中的每一个元素;p = b+n
generate(b,e,f);将 f() 赋予[b,e)中的每一个元素
p = generate_n(b,n,f);将 f() 赋予[b,b+n)中的每一个元素;p = b+n
uninitialized_fill(b,e,v);[b,e)中的每一个元素初始化为 v
p = uninitialized_fill_n(b,n,v);[b,b+n)中的每一个元素初始化为 v;p = b+n
uninitialized_copy(b,e,out);[out,out+(e-b))中的每一个元素初始化为[b,e)中对应的元素;p = out+(e-b)
p = uninitialized_copy_n(b,n,out);[out,out+n]中的每一个元素初始化为[b,b+n)中对应的元素;p = out+n

排序和搜索

排序

默认的比较操作是<运算符;值 a 和 b 的相等性通过!(a<b)&&!(b<a)来判定,而不是使用==运算符。
算法 sort() 要求使用随机访问迭代器。
基础的 sort() 算法很高效,平均时间复杂性为 O ( N ∗ log ⁡ ( N ) ) O(N*\log(N)) O(Nlog(N))。。
如果需要一个稳定的排序算法,可以使用 stable_sort(),其平均时间复杂性为 O ( N ∗ log ⁡ ( N ) log ⁡ ( N ) ) O(N*\log(N)\log(N)) O(Nlog(N)log(N));当系统有足够的额外内存时,可缩短为 O ( N ∗ log ⁡ ( N ) ) O(N*\log(N)) O(Nlog(N))
算法 stable_sort() 可以保证相等元素的相对顺序,然而 sort() 则不能保证。
如果需要由 partial_sort() 排序的元素数少于元素总数,则其时间复杂性接近 O ( N ) O(N) O(N)
算法 partial_sort_copy() 的目标必须是一个随机访问迭代器。
算法 nth_element() 只需将升序结果中排在第 n 位的元素放置到正确位置即可(即,之前的元素都不大于它,之后的元素都不小于它)。

算法功能
sort(b,e);排序[b,e)
sort(b,e,f);排序[b,e);用f(*p,*q)作为比较标准
stable_sort(b,e);排序[b,e);保持相等元素的相对顺序
stable_sort(b,e,f);排序[b,e);保持相等元素的相对顺序;用f(*p,*q)作为比较标准
partial_sort(b,m,e);部分排序[b,e);令[b,m)有序即可,[m,e)不必有序
partial_sort(b,m,e,f);部分排序[b,e);令[b,m)有序即可,[m,e)不必有序;用f(*p,*q)作为比较标准
p = partial_sort_copy(b,e,b2,e2);部分排序[b,e);排好前e2-b2(或前e-b)个元素拷贝到[b2,e2);p 为 e2b2 +(e-b) 中的较小者
p = partial_sort_copy(b,eb2,e2,f);部分排序[b,e);排好前e2-b2(或前e-b)个元素拷贝到[b2,e2);p 为 e2b2 +(e-b) 中的较小者;用 f 比较元素
is_sort(b,e);[b,e)已排序?
is_sort(b,e,f);[b,e)已排序?;用 f 比较元素
p = is_sort_until(b,e);p 指向[b,e)中第一个不符合升序的元素
p = is_sort_until(b,e,f);p 指向[b,e)中第一个不符合升序的元素;用 f 比较元素
nth_element(b,n,e);*n的位置恰好是[b,e)排序后它应处的位置;即[b,n)中的元素都<= *n[n,e)中的元素都>= *n
nth_element(b,n,e,f);*n的位置恰好是[b,e)排序后它应处的位置;即[b,n)中的元素都<= *n[n,e)中的元素都>= *n;用 f 比较元素
reverse(b,e);[b,e)中的元素逆序排序
p = reverse_copy(b,e,out);[b,e)中的元素逆序拷贝至[out,p)

二分搜索

binary_serach() 系列算法提供有序序列上的二分搜索。
一旦序列已排序,就可以使用二分搜索查找元素了。

算法功能
p = lower_bound(b,e,v);p 指向[b,e)中 v 首次出现的位置
p = lower_bound(b,e,v,f);p 指向[b,e)中 v 首次出现的位置;用 f 比较元素
p = upper_bound(b,e,v);p 指向[b,e)中第一个大于 v 的元素
p = upper_bound(b,e,v,f);p 指向[b,e)中第一个大于 v 的元素;用 f 比较元素
binary_search(b,e,v);v 在有序序列[b,e)中吗?
binary_search(b,e,v,f);v 在有序序列[b,e)中吗?;用 f 比较元素
pair(p1,p2) = equal_range(b,e,v);[p1,p2)[b,e)中值为 v 的子序列;通常用二分搜索查找 v
pair(p1,p2) = equal_range(b,e,v,f);[p1,p2)[b,e)中值为 v 的子序列;通常用二分搜索查找 v;用 f 比较元素

merge()

算法 merge() 将两个有序序列合并为一个序列。
算法 merge() 可以接受不同类别的序列和不同类型的元素。

算法功能
p = merge(b,e,b2,e2,out);合并两个有序序列[p1,p2)[b,e),结果写入[out,p)
p = merge(b,e,b2,e2,out,f);合并两个有序序列[p1,p2)[b,e),结果写入[out,out+p);用 f 比较元素
inplace_merge(b,m,e);原址合并;将两个有序子序列[b,m)[m,e)合并为有序序列[b,e)
inplace_merge(b,m,e,f);原址合并;将两个有序子序列[b,m)[m,e)合并为有序序列[b,e);用 f 比较元素

集合算法

这些算法将序列当作一个元素集合来处理,并提供基本的集合操作。
输入序列应是排好序的,输出序列也会被排序。

算法功能
includes(b,e,b2,e2);[b,e)中的所有元素也都在[b2,e2)中?
includes(b,e,b2,e2,f);[b,e)中的所有元素也都在[b2,e2)中?用 f 比较元素
p = set_union(b,e,b2,e2,out);创建一个有序序列[out,p) ,包含[b,e)[b2,e2)中的所有元素
p = set_union(b,e,b2,e2,out,f);创建一个有序序列[out,p) ,包含[b,e)[b2,e2)中的所有元素;用 f 比较元素
p = set_intersection(b,e,b2,e2,out);创建一个有序序列[out,p) ,包含[b,e)[b2,e2)中共同的元素
p = set_intersection(b,e,b2,e2,out,f);创建一个有序序列[out,p) ,包含[b,e)[b2,e2)中共同的元素;用 f 比较元素
p = set_difference(b,e,b2,e2,out);创建一个有序序列[out,p) ,其元素在[b,e)中但不在[b2,e2)
p = set_difference(b,e,b2,e2,out,f);创建一个有序序列[out,p) ,其元素在[b,e)中但不在[b2,e2)中;用 f 比较元素
p = set_symmetric_difference(b,e,b2,e2,out);创建一个有序序列[out,p) ,其元素在[b,e)中或在[b2,e2)中,但不同时在两者中
p = set_symmetric_difference(b,e,b2,e2,out,f);创建一个有序序列[out,p) ,其元素在[b,e)中或在[b2,e2)中,但不同时在两者中;用 f 比较元素

堆是一种按最大值优先的方式组织元素的紧凑数据结构。
堆算法允许将一个随机访问序列作为堆处理。
堆的关键特点是提供了快速插入新元素和快速访问最大元素的能力;其主要用途是实现优先队列。

算法功能
make_heap(b,e);[b,e)整理为一个堆
make_heap(b,e,f);[b,e)整理为一个堆;用 f 比较元素
push_heap(b,e);*(e-1)添加到堆[b,e-1)中,使得[b,e)还是一个堆
push_heap(b,e,f);*(e-1)添加到堆[b,e-1)中,使得[b,e)还是一个堆;用 f 比较元素
pop_heap(b,e);从堆[b,e)中删除最大值(*b*(e-1)交换后删除*(e-1)),[b,e-1)保持堆结构
pop_heap(b,e,f);从堆[b,e)中删除最大值(*b*(e-1)交换后删除*(e-1)),[b,e-1)保持堆结构;用 f 比较元素
sort_heap(b,e);排序堆[b,e)
sort_heap(b,e,f);排序堆[b,e);用 f 比较元素
is_heap(b,e);[b,e)是一个堆吗?
is_heap(b,e,f);[b,e)是一个堆吗?用 f 比较元素
p = is_heap_until(b,e);p 是满足[b,p)堆的最大位置
p = is_heap_until(b,e,f);p 是满足[b,p)堆的最大位置;用 f 比较元素

lexicographical_compare()

字典序比较就是我们用来排序字典中单词的规则。

算法功能
lexicographical_compare(b,e,b2,e2);[b,e) < [b2,e2)
lexicographical_compare(b,e,b2,e2,f);[b,e) < [b2,e2)?用 f 比较元素

最大值和最小值

如果比较两个左值,返回的是指向结果的引用;否则,返回一个右值。
但是,接受左值的版本接受的是 const 左值,因此永远也不能修改这些函数的返回结果。

算法功能
x = min(a,b);x 是 a 和 b 中的较小者
x = min(a,b,f);x 是 a 和 b 中的较小者,用 f 比较元素
x = min({elem});x 是 {elem} 中的最小元素
x = min({elem},f);x 是 {elem} 中的最小元素,用 f 比较元素
x = max(a,b);x 是 a 和 b 中的较大者
x = max(a,b,f);x 是 a 和 b 中的较大者,用 f 比较元素
x = max({elem});x 是 {elem} 中的最大元素
x = max({elem},f);x 是 {elem} 中的最大元素,用 f 比较元素
pair(x,y) = minmax(a,b);x 为 min(a,b),y 为 max(a,b)
pair(x,y) = minmax(a,b,f);x 为 min(a,b,f),y 为 max(a,b,f)
pair(x,y) = minmax({elem});x 为 min({elem}),y 为 max({elem})
pair(x,y) = minmax({elem},f);x 为 min({elem},f),y 为 max({elem},f)
p = min_element(b,e);p 指向[b,e)中的最小元素或 e
p = min_element(b,e,f);p 指向[b,e)中的最小元素或 e,用 f 比较元素
p = max_element(b,e);p 指向[b,e)中的最大元素或 e
p = max_element(b,e,f);p 指向[b,e)中的最大元素或 e,用 f 比较元素
pair(x,y) = minmax_element(b,e);x 为 min_element(b,e),y 为 max_element(b,e)
pair(x,y) = minmax_element(b,e,f);x 为 min_element(b,e,f),y 为 max_element(b,e,f)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

移动零算法(leetcode第283题)

题目描述&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。示例 1:输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2:输入: n…

用uniapp写一个点击左侧可以滑动的menu

完成后的图片&#xff08;点击左侧右边或滑动&#xff0c;滑动右边左侧的选中也会变化&#xff09;&#xff1a; 数据js &#xff08;classifyData&#xff09;&#xff1a; export default[{"name": "女装","foods": [{"name": &q…

消息幂等:如何保证消息不被重复消费?

应用的幂等是在分布式系统设计时必须要考虑的一个方面&#xff0c;如果对幂等没有额外的考虑&#xff0c;那么在消息失败重新投递&#xff0c;或者远程服务重试时&#xff0c;可能会出现许多诡异的问题。本文一起来看一下&#xff0c;在消息队列应用中&#xff0c;如何处理因为…

命名之美:探索Java的标识符与命名规范

目录 ​编辑 前言 一、Java关键字&#xff1a; class&#xff1a; public、private、protected&#xff1a; static&#xff1a; final&#xff1a; void&#xff1a; int、double、char、boolean&#xff1a; if、else、switch&#xff1a; for、while、do&#xf…

01到底应该怎么理解“平均负载”

1、如何了解系统的负载情况&#xff1f; 每次发现系统变慢时&#xff0c; 我们通常做的第⼀件事&#xff0c; 就是执⾏top或者uptime命令&#xff0c; 来了解系统的负载情况。 ⽐如像下⾯这样&#xff0c; 我在命令⾏⾥输⼊了uptime命令&#xff0c; 系统也随即给出了结果。 …

微服务组件OpenFeign的学习

OpenFeign 添加依赖OpenFeign的简单使用OpenFeign日志配置OpenFeign超时时间配置 添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>OpenFeign的…

思码逸关钦杰:聊聊研效管理中的数据操纵

3月25日&#xff0c;思码逸咨询总监、研发过程提效专家关钦杰在 QECon 质效城市论坛【深圳站】分享了主题为《聊聊研效管理中的数据操纵》的演讲。 以下内容根据关钦杰老师分享内容整理&#xff1a; 在生活中&#xff0c;当我们去描述客观事实的时候&#xff0c;我们经常要用…

【Source Insight4.0】解决注释中文乱码

本来用的好好的&#xff0c;结果今天创建一个新的项目就出现注释中文乱码&#xff01;&#xff01;&#xff01; 然后上网查找说要修改为【Default encoding” &#xff1a;改成System Default(Windows ANSI) 或者Chinese Simplified(GB2312)】但是我的并没有效果。 最后是选…

Spring Boot Logging中文文档

本文为官方文档直译版本。原文链接 Spring Boot Logging中文文档 引言日志格式控制台输出彩色输出 文件输出文件轮转日志级别日志组使用日志关机钩子自定义日志配置Logback 扩展特定配置文件的配置环境属性 Log4j2 扩展特定配置文件的配置环境属性查找Log4j2 系统属性 引言 Sp…

Frida05 - 高级API用法

参考文档 https://api-caller.com/2019/03/30/frida-note/ https://frida.re/docs/javascript-api/#frida 数组打印 测试代码&#xff1a; private static class Bean {String a;int b;float c; }private void test() {Bean[] beans new Bean[3];beans[0] new Bean();be…

深度学习笔记_6经典预训练网络LeNet-18解决FashionMNIST数据集

1、 调用模型库&#xff0c;定义参数&#xff0c;做数据预处理 import numpy as np import torch from torchvision.datasets import FashionMNIST import torchvision.transforms as transforms from torch.utils.data import DataLoader import torch.nn.functional as F im…

Redis——Redis常用命令

Redis提供了丰富的命令&#xff0c;可以对数据库和各种数据类型进行操作&#xff0c;这些命令可以在Windows和Linux中使用。 1、键值相关命令 1.1、KEYS KEYS用于返回满足pattern的所有key&#xff0c;pattern支持以下通配符&#xff1a; *&#xff1a;匹配任意字符。&…

Python教程81:函数的位置参数、默认参数、动态参数、关键字参数(入门必看)

1.形式参数&#xff08;Formal Parameters&#xff09;和实际参数&#xff08;Actual Parameters&#xff09;是函数或方法定义和调用过程中的两个重要概念。举个例子&#xff0c;在下面的greet函数中&#xff0c;当我们调用greet(“李白”)时&#xff0c;"李白"就是…

electron这样使用更安全

背景&#xff1a; electron大家平时为了方便使用&#xff0c;或是一些网上demo的引导&#xff0c;会让渲染进程的业务界面支持直接使用nodejs&#xff0c;这种开发方式有一定的安全隐患&#xff0c;如果业务界面因为xss之类的漏洞被注入其他代码&#xff0c;危害非常大&#x…

Spring之容器:IOC(3)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

华为云CodeArts Repo常见问答汇总

1.【Repo】codearts Repo最大支持上传文件大小 答&#xff1a;参考链接 https://support.huaweicloud.com/productdesc-codehub/codehub_pdtd_0005.html • 单文件上传大小限制&#xff08;评论中上传附件&#xff09;<50MB。 • 单文件上传大小限制&#xff08;代码…

某联合产权交易所持续购买监控易产品的维保服务,提升IT运维保障能力

在信息化时代&#xff0c;企业信息化的程度已经成为影响其核心竞争力的重要因素。某联合产权交易所&#xff08;以下简称“交易所”&#xff09;作为行业领导者&#xff0c;一直以来都积极推进信息化建设&#xff0c;致力于提升运维管理水平&#xff0c;以适应日益激烈的市场竞…

Rust 嵌入式开发

Rust 进行嵌入式开发: https://xxchang.github.io/book/intro/index.html # 列出所有目标平台 rustup target list# 安装目标平台工具链 rustup target add thumbv7m-none-eabi# 创建工程 cargo new demo && cd demo cargo add cortex-m-rt cargo add panic-halt carg…

二十九、获取文件属性及相关信息

二十九、获取文件属性及相关信息QFileInfo QFileInfo 提供有关文件在文件系统中的名称 位置 &#xff08;路径&#xff09;、访问权限及它是目录还是符号链接、等信息。文件的大小、最后修改/读取时间也是可用的。QFileInfo 也可以被用于获取信息有关 Qt resource . QFileInf…

科技的成就(五十四)

511、线路板按层数来分的话分为单面板&#xff0c;双面板&#xff0c;和多层线路板三个大的分类。线路板按特性来分的话分为软板(FPC)&#xff0c;硬板(PCB)&#xff0c;软硬结合板(FPCB)。是当代电子元件业中最活跃的产业&#xff0c;其行业增长速度一般都高于电子元件产业3个…