特此声明:该博客仅为学习使用,为自己和他人创建一个查询STL算法的索引,本博客中引出的算法将会告知所在头文件、所需参数、返回类型、算法描述与函数声明。该博客参考自《Using and Extending the C++ Standard Templatelibrary》——Matthew H.Austern
鉴于会有一些不是太了解迭代器和指针,容器和数组,仿函数和普通函数等等的人,因此在find与find_if中,如何使用有所演示,其余的算法中,只会演示一种用法,除非有特殊用法。
请观看原博客:STL算法(上)
非质变算法
线性查找
find
用法:find(first, last, value)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class EqualityComparable>
InputIterator find(InputIterator first, InputIterator last, const EqualityComparable& value);
该算法会在区间[first, last)
线性查找,寻找指定值value
。会返回[first, last)
中第一个与value
值相等(即*i==value*
)的迭代器。否则会返回last
。
复杂度:线性O(n)
, 最多有(last-first)
次比较
例子:
int main() {
// 容器执行
vector<int> v = {11, 12, 13, 14, 15, 16, 17, 18, 19};
auto it = find(v.begin(), v.end(), 15);
cout << *it << endl;
// 数组执行
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int N = sizeof(arr) / sizeof(int);
int* ait = find(arr, arr + N, 5);
cout << *ait << endl;
return 0;
}
输出:
15
5
find_if
用法:find_if(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class Predicate>
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);
和find
类似,不过比find
更具有一般性,该算法会在区间[first, last)
线性查找,寻找满足某种条件的元素,即满足pred(*i)
为true
。会返回[first, last)
中第一个满足该条件的迭代器。否则会返回last
。
复杂度:线性O(n)
, 最多有(last-first)
次pred
例子:
class class_cmp {
public:
// 仿函数 即寻找容器中第一个小于0的值的迭代器
bool operator()(int n) {
return n < 0;
}
};
//普通函数 即返回容器中第一个值在0和10之间的迭代器
bool function_cmp(int n) {
return n > 0 && n < 10;
}
int main() {
vector<int> v = {8, 12, 9, -7, 0, -5, -10};
auto it1 = find_if(v.begin(), v.end(), function_cmp);
auto it2 = find_if(v.begin(), v.end(), class_cmp());
cout << *it1 << " " << *it2 << endl;
int arr[] = {-10, -5, 0, -7, 9, 12, 8};
int N = sizeof(arr) / sizeof(int);
int* ait1 = find_if(arr, arr + N, function_cmp);
int* ait2 = find_if(arr, arr + N, class_cmp());
cout << *ait1 << " " << *ait2 << endl;
return 0;
}
输出:
8 -7
9 -10
adjacent_find
用法:adjacent_find(first, last)
或adjacent_find(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class BinaryPredicate>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred);
和find
类似,adjacent_find
算法会在[first, last)
中线性查找, 差异在于find
是对单个元素查找, adjacent_find
是针对两个相邻元素查找。该函数重载了两个版本。
第一个版本查找两个相等的相邻元素,返回[first, last)
中第一个满足*i==*(i+1)
的迭代器i
,否则返回last
·
第二个版本则更加一般化,与find_if
类似,返回[first, last)
中第一个满足某种条件的元素, 即满足pred(*i, *(i+1))
为true
的迭代器i
,否则返回last
。
复杂度:线性O(n)
, 最多有(last-first-1)
次比较动作
例子:
class cmp {
public:
// 返回x与y同为5的倍数则返回true
bool operator()(int x, int y) {
return x % 5 == 0 && y % 5 == 0;
}
};
int main() {
vector<int> v1 = {11, 12, 13, 14, 14, 15, 16, 17, 18, 19};
auto it1 = adjacent_find(v1.begin(), v1.end());
cout << *it1 << endl;
vector<int> v2 = {9, 14, 20, 25, 27, 35};
auto it2 = adjacent_find(v2.begin(), v2.end(), cmp());
cout << *it2 << endl;
return 0;
}
输出:
14
20
find_first_of
用法:find_first_of(first1, last1, first2, last2)
或find_first_of(first1, last1, first2, last2, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class ForwardIterator>
InputIterator find_first_of(InputIterator first1, InputIterator last1,
ForwardIterator first2, Forward_iterator last2);
template <class InputIterator, class ForwardIterator, class BinaryPredicate>
InputIterator find_first_of(InputIterator first1, InputIterator last1,
ForwardIterator first2, ForwardIteraotr last2,
BinaryPredicate pred);
find_first_of
和find
非常类似,它会在[first1, last1)
中线性查找, 区别在于find
查找某个特定值,find_first_of
查找任何数量的值。该函数重载了两个版本。
第一个版本会从[first1, last1)
中查找任何出现于[first2, last2)
的值,返回[first1, last1)
内满足[first2, last2)中某个iterator j,使得*i == *j
的迭代器i
, 否则返回last1
第二个版本更加的一般化,会从[first1, last1)
中查找任何满足于[first2, last2)
的值,返回[first1, last1)
内满足[first2, last2)中某个iterator j,使得pred(*i, *j)
的迭代器i
,否则返回last1
复杂度:O(n*m)
,最多有(last1-first1)*(last2-first2)
次比较动作
例子:
int main() {
vector<int> v1 = {11, 12, 13, 14, 14, 15, 16, 17, 18, 19};
vector<int> v2 = {9, 14, 20, 25, 27, 35};
auto it = find_first_of(v1.begin(), v1.end(), v2.begin(), v2.end());
cout << *it << endl;
return 0;
}
输出:
14
子序列匹配
search
用法:search(first1, last1, first2, last2)
或search(first1, last1, first2, last2, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2);
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred);
search
和find
有所不同,find
只在[first1, last1)
中寻找一个元素进行匹配比较,而search
则在[first1, last1)
中寻找一个[first2, last2)
区间,并返回一个迭代器,指向该子序列的开头,如果不存在该子序列,则返回last1
第一个版本将各个迭代器使用==
比较,如(*(i+(j-first2)) == *j)
第二个版本则使用外界提供的pred
函数,即pred(*(i+(j-first2)), *j)
为true
复杂度:O(n*m)
,最多有(last1-first1)*(last2-first2)
次比较动作
例子:
int main() {
vector<int> v1 = {1, 1, 3, 1, 2, 3, 4, 1, 2, 6};
vector<int> v2 = {1, 2};
auto it = search(v1.begin(), v1.end(), v2.begin(), v2.end());
for(; it != v1.end(); ++it) {
cout << *it << " ";
}
return 0;
}
输出:
1 2 3 4 1 2 6
find_end
用法:find_end(first1, last1, first2, last2)
或find_end(first1, last1, first2, last2, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2);
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred);
这里虽然函数名叫做find_end
, 但是它更像是search
,它与search
一样,会从[first1, last1)
中寻找与[first2, last2)
相同的子序列,区别在于,search
寻找的是第一个这样的子序列,而find_end
寻找的则是最后一个这样的子序列。若不存在则返回last1
该函数与其他函数一样,重载了两个版本, 第一个版本则是以operator==
进行比较(*(i+(j-first2)) == *j
), 而第二个版本则是以pred()
函数来进行比较。(pred(*(i+(j-first2)), *j)
)
复杂度:O(n*m)
,最多有(last1-first1)*(last2-first2)
次比较动作
例子:
int main() {
vector<int> v1 = {1, 1, 3, 1, 2, 3, 4, 1, 2, 6};
vector<int> v2 = {1, 2};
auto it = find_end(v1.begin(), v1.end(), v2.begin(), v2.end());
for(; it != v1.end(); ++it) {
cout << *it << " ";
}
return 0;
}
输出:
1 2 6
search_n
用法:search_n(first, last, count, value)
或search_n(first, last, count, value, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Integer, class T>
ForwardIterator search_n(ForwardIterator first, ForwardIterator last,
Integer count, const T& value);
template <class ForwardIterator, class Integer, class T, class BinaryPredicate>
ForwardIterator search_n(ForwardIterator first, ForwardIterator last,
Integer count, const T& value, BinaryPredicate pred);
search_n
查找[first, last)
之中由count
个相邻元素形成的子序列,其中所有元素都为value
。它返回该子序列的开头,若没有这样的子序列,则返回last
其中count
可以为0,此时无论value
值为多少都会返回first
同样的,该函数与其他函数一样,重载了两个版本, 第一个版本则是以operator==
进行比较, 而第二个版本则是以pred()
函数来进行比较。
复杂度:线性O(n)
,最多有last-first
次比较动作
例子:
int main() {
vector<int> v = {1, 1, 3, 1, 1, 1, 4, 1, 2, 6};
auto it1 = search_n(v.begin(), v.end(), 2, 1);
auto it2 = search_n(v.begin(), v.end(), 3, 1);
for(; it1 != v.end(); ++it1) {
cout << *it1 << " ";
}
cout << endl;
for(; it2 != v.end(); ++it2) {
cout << *it2 << " ";
}
return 0;
}
输出:
1 1 3 1 1 1 4 1 2 6
1 1 1 4 1 2 6
计算元素个数
count
用法:count(first, last, value)
或count(first, last, value, n)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class EqualityComparable>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const EqualityComparable& value);
template <class InputIterator, class EqualityComparable, class Size>
void count(InputIterator first, InputIterator last,
const EqualityComparable& value, Size& n);
count
算法可以统计[first, last)
区间中与value
值相等的元素个数
count
有两个版本,但与前面不同,这两个版本做的是相同的事情,但只是接口不同而已。接口二定义于HP STL
中,但在C++ standard
只包含了版本一。
版本二的接口非常不方便,那是因为原始的HP STL
中并没有萃取的定义即没有iterator_traits
复杂度:线性O(n)
,只执行last-first
次比较动作
例子:
int main() {
vector<int> v = {1, 1, 3, 1, 2, 3, 4, 1, 2, 6};
auto co = count(v.begin(), v.end(), 1);
cout << co << endl;
return 0;
}
输出:
4
count_if
用法:count(first, last, pred)
或count(first, last, pred, n)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, Predicate pred);
template <class InputIterator, class Predicate, class Size>
void count(InputIterator first, InputIterator last,
Predicate pred, Size& n);
count_if
算法可以统计[first, last)
区间中满足pred(*i)
的元素个数,count
与count_if
之间的关系跟find
与find_if
差不多,count_if
比之count
更加一般化
count_if
与count
一样有两个版本,只是接口不同而已。同样的,接口二定义于HP STL
中,但在C++ standard
只包含了版本一。
复杂度:线性O(n)
,只执行last-first
次比较动作
例子:
class cmp {
public:
// 统计偶数的个数
bool operator()(int x) {
return x % 2 == 0;
}
};
int main() {
vector<int> v = {1, 2, 3, 1, 2, 3, 4, 1, 2, 6};
auto co = count_if(v.begin(), v.end(), cmp());
cout << co << endl;
return 0;
}
输出:
5
for_each
用法:for_each(first, last, fun)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last,
UnaryFunction fun);
for_each
可以将fun
套用于[first, last)
的每一个元素上,如果函数fun
有返回值, 则忽略该返回值,该函数的返回值为该函数(如果该函数是仿函数,则返回该类,如果是普通函数, 则返回该函数的函数指针)。
与普通调用函数同理,若要改变原来容器内的值, 则函数的参数需要是引用或指针。
复杂度:线性O(n)
,只执行last-first
次比较动作
例子:
class cmp {
public:
void operator()(int& x) {
x += 10;
}
};
int main() {
vector<int> v = {1, 2, 3, 1, 2, 3, 4, 1, 2, 6};
auto co = for_each(v.begin(), v.end(), cmp());
for(auto x : v) {
cout << x << " ";
}
return 0;
}
输出:
11 12 13 11 12 13 14 11 12 16
比较两个区间
equal
用法:equal(first1, last1, first2)
或equal(first1, last1, first2, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2>
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator first2);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(InputIterator1 first1, InputIterator1, last1,
InputIterator2 first2, BinaryPredicate pred);
将[first1, last1)
和[first2, first2+(last1-first1))
内的元素一一比较,如果都相等,则该函数返回true
,否则返回false
。
equal
一样有两个版本,第一个版本使用operator==
来进行比较(*i == *(first2+(i-first1))
),而版本二则使用pred()
进行比较(pred(*i, *(first2+(i-first1)))
)。
复杂度:线性O(n)
,最多执行last1-first1
次比较动作
例子:
int main() {
vector<int> v1 = {1, 2, 3, 1, 2};
vector<int> v2 = {2, 1, 3, 2, 1};
vector<int> v3 = {1, 2, 3, 1, 2};
if(equal(v1.begin(), v1.end(), v2.begin())) {
cout << "equal" << endl;
} else {
cout << "not equal" << endl;
}
if(equal(v1.begin(), v1.end(), v3.begin())) {
cout << "equal" << endl;
} else {
cout << "not equal" << endl;
}
return 0;
}
输出:
not equal
equal
mismatch
用法:mismatch(first1, last1, first2)
或mismatch(first1, last1, first2, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2>
mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
pair<InputIterator1, InputIterator2>
mismatch(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate pred);
该函数翻译过来就是不匹配,函数mismatch
会将区间[first1, last1)
与区间[first2, first2+(last1-first1))
第一个元素值不同的位置,该位置由一个[first1, last1)
的迭代器与一个[first2, first2+(last1-first1))
的迭代器组成
mismatch
一样有两个版本,第一个版本使用operator==
来进行比较(*i == *(first2+(i-first1))
),而版本二则使用pred()
进行比较(pred(*i, *(first2+(i-first1)))
)。
复杂度:线性O(n)
,最多执行last1-first1
次比较动作
例子:
int main() {
vector<int> v1 = {1, 2, 3, 1, 2};
vector<int> v2 = {1, 2, 4, 1, 2};
auto pa = mismatch(v1.begin(), v1.end(), v2.begin());
cout << *pa.first << " " << *pa.second << endl;
return 0;
}
输出:
3 4
lexicographical_compare
用法:lexicographical_compare(first1, last1, first2, last2)
或lexicographical_compare(first1, last1, first2, last2, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2>
bool lexicographical_compare(InputIterator1 first1, I
3nputIterator1 last1,
InputIterator2 first2, InputIteraotr2 last2);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred);
该函数翻译过来就是以字典排序法作比较,如果[first1, last1)
小于[first2, last2)
,则该函数返回true
,否则返回false
字典排序方式指一个元素接着一个元素的排序,如果说*first1
小于*first2
,则[first1, last1)
小于[first2, last2)
,如果*first1
大于*first2
,则[first1, last1)
大于[first2, last2)
,如果*first1
等于*first2
,则比较下一个元素。
第一个版本使用operator<
进行比较,第二个版本使用pred()
进行比较
复杂度:线性O(n)
,最多执行2 * min(last1-first1, last2-first2)
次比较动作
例子:
int main() {
vector<int> v1 = {1, 2, 3, 1, 2};
vector<int> v2 = {1, 2, 4, 1, 2};
vector<int> v3 = {1, 2, 2, 1, 2};
if(lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end())) {
cout << "v1 less than v2" << endl;
} else {
cout << "v1 not less than v2" << endl;
}
if(lexicographical_compare(v1.begin(), v1.end(), v3.begin(), v3.end())) {
cout << "v1 less than v3" << endl;
} else {
cout << "v1 not less than v3" << endl;
}
return 0;
}
输出:
v1 less than v2
v1 not less than v3
最值
min
用法:min(a, b)
或min(a, b, pred)
定义头文件:<algorithm>
函数原型:
template <class LessThanCompare>
const LessThanCompare& min(const LessThanCompare& a, const LessThanCompare& b);
template <class T, class BinaryPredicate>
const T& min(const T& a, const T& b, BinaryPredicate pred);
大多数的STL
算法都是作用于元素所形成的区间的上,而min
则是少数作用于以引用传入的单一元素上的算法之一。min
返回两个引用中比较小的一个,如果无法比较出大小,则返回第一个引用a
min
有两个版本,第一个版本采用operator<
进行比较,第二个版本则使用自己传入的函数pred()
进行比较。
复杂度:常数O(1)
,仅执行1
次比较动作
例子:
int main() {
vector<int> v = {1, 2, 3, 1, 2};
auto a = min(*v.begin(), *(v.begin() + 1));
cout << a << endl;
return 0;
}
输出:
1
max
用法:max(a, b)
或max(a, b, pred)
定义头文件:<algorithm>
函数原型:
template <class LessThanCompare>
const LessThanCompare& max(const LessThanCompare& a, const LessThanCompare& b);
template <class T, class BinaryPredicate>
const T& max(const T& a, const T& b, BinaryPredicate pred);
大多数的STL
算法都是作用于元素所形成的区间的上,而max
则是少数作用于以引用传入的单一元素上的算法之一。max
返回两个引用中比较大的一个,如果无法比较出大小,则返回第一个引用a
max
有两个版本,第一个版本采用operator>
进行比较,第二个版本则使用自己传入的函数pred()
进行比较。
复杂度:常数O(1)
,仅执行1
次比较动作
例子:
int main() {
vector<int> v = {1, 2, 3, 1, 2};
auto a = max(*v.begin(), *(v.begin() + 1));
cout << a << endl;
return 0;
}
输出:
2
min_element
用法:min_element(first, last)
或min_element(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
ForwardIterator min_element(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator>
ForwardIterator min_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate pred)
算法min_element
可以寻找[first, last)
区间内最小的元素,它会返回第一个最小元素值的迭代器,若该区间为空,则返回last
min_element
有两个版本,第一个版本采用operator<
进行比较,第二个版本则使用自己传入的函数pred()
进行比较。
复杂度:线性O(n)
,执行(last - first) - 1
次比较动作
例子:
int main() {
vector<int> v = {2, 1, 3, 6, 2};
auto a = min_element(v.begin(), v.end());
cout << *a << endl;
return 0;
}
输出:
1
max_element
用法:max_element(first, last)
或max_element(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
ForwardIterator max_element(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator>
ForwardIterator max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate pred)
算法max_element
可以寻找[first, last)
区间内最大的元素,它会返回第一个最大元素值的迭代器,若该区间为空,则返回last
max_element
有两个版本,第一个版本采用operator>
进行比较,第二个版本则使用自己传入的函数pred()
进行比较。
复杂度:线性O(n)
,执行(last - first) - 1
次比较动作
例子:
int main() {
vector<int> v = {2, 1, 3, 6, 2};
auto a = max_element(v.begin(), v.end());
cout << *a << endl;
return 0;
}
输出:
6
质变算法
拷贝
copy
用法:copy(first, last, result)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
算法copy
可以将[first, last)
中的元素拷贝到result
中,即复制到区间[result, result+(last-first))
上,会执行赋值操作*result = *first
等等,返回值为result+(last-first)
copy
只能用来改变[result, result+(last-first))
中的元素,不能用来产生新元素,即不能用来安插在空的容器中。
若想使用copy
来对空的元素进行插入,可使用后文会介绍的insrt_iterator
复杂度:线性O(n)
,执行last - first
次赋值动作
例子:
int main() {
vector<int> v1 = {2, 1, 3, 6, 2};
vector<int> v2(5);
// vector<int> v3; // 空容器
// copy(v1.begin(), v1.end(), v3.begin()); //error
copy(v1.begin(), v1.end(), v2.begin());
for(auto x : v2) {
cout << x << " ";
}
return 0;
}
输出:
2 1 3 6 2
copy_backward
用法:copy_backward(first, last, result)
定义头文件:<algorithm>
函数原型:
template <class BidirectionIterator1, class BidirectionIterator2>
BidirectionIterator2 copy_backward(BidirectionIterator1 first,
BidirectionIterator1 last,
BidirectionIterator2 result);
算法copy_backward
与copy
一样,可以将[first, last)
中的元素拷贝到result
中,但是是复制到区间[result-(last-first), result)
上,即copy
是由前向后复制,copy_backward
由后向前复制,会执行赋值操作*(result-1) = *(first-1)
等等,返回值为result-(last-first)
,
copy_backward
与copy
一样,只能用来改变[result-(last-first), result)
中的元素,不能用来产生新元素,即不能用来安插在空的容器中。
复杂度:线性O(n)
,执行last - first
次赋值动作
例子:
int main() {
vector<int> v1 = {2, 1, 3, 6, 2};
vector<int> v2(5);
copy_backward(v1.begin(), v1.end(), v2.end());
for(auto x : v2) {
cout << x << " ";
}
return 0;
}
输出:
2 1 3 6 2
元素互换
swap
用法:swap(a, b)
定义头文件:<algorithm>
函数原型:
template <class Assignable>
void swap(Assignable& a, Assignable& b);
算法swap
与min
和max
一样,是少数作用于以引用传入的单一元素上的算法之一,它可以将a
和b
的值互换。
为此可以实现完全的一般化,但是对于STL
中的所有容器,都会提供其特化版本的swap
,所以,若想交换两个容器,则使用该容器的特化版本。
复杂度:常数O(1)
,仅执行1
次交换动作
例子:
int main() {
int a = 10;
int b = 20;
swap(a, b);
cout << "a:" << a << endl;
cout << "b:" << b << endl;
return 0;
}
输出:
a:20
b:10
iter_swap
用法:iter_swap(a, b)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator1, class ForwardIterator2>
inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b);
与算法swap
类似,是少数作用于以引用传入的单一元素上的算法之一,它可以将a
和b
的值互换。等价于swap(*a, *b)
现如今已经几乎不再需要该版本的swap
,C++
标准库之所以还保留该函数,只是为了向下兼容
复杂度:常数O(1)
,仅执行1
次交换动作
例子:
int main() {
int a = 10;
int b = 20;
iter_swap(&a, &b);
cout << "a:" << a << endl;
cout << "b:" << b << endl;
return 0;
}
输出:
a:20
b:10
swap_ranges
用法:swap_ranges(first1, last1, first2)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator last1,
ForwardIterator2 first2);
算法swap_ranges
可以对两个大小相同的区间内容进行互换,也就是会将区间[first1, last1)
与区间[first2, first2+(last1-first1))
中的对应元素进行交换,返回值为first2+(last1-first1)
复杂度:线性O(n)
,执行last1 - first1
次交换动作
例子:
int main() {
constexpr int a = 5;
int arr1[a] = {0, 1, 2, 3, 4};
int arr2[a] = {5, 6, 7, 8, 9};
swap_ranges(arr1, arr1+a, arr2);
cout << "arr1:";
for(auto x : arr1) {
cout << x << " ";
}
cout << endl;
cout << "arr2:";
for(auto x : arr2) {
cout << x << " ";
}
cout << endl;
return 0;
}
输出:
arr1:5 6 7 8 9
arr2:0 1 2 3 4
tansform
用法:transform(first, last, result, pred)
或transform(first1, last1, first2, result, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator, class UnaryFunction>
OutputIterator transform(InputIterator first, InputIterator last,
OutputIterator result, UnaryFunction pred);
template <class InputIterator, class OutputIterator, class BinaryFunction>
OutputIterator transform(InputIterator first1, InputIterator last1,
InputIterator first2, OutPutIterator result,
BinayFunction pred);
该函数与for_each
类似,可以搭配一个外部函数对区间内的元素进行某种运算,差别在于,for_each
会忽略外部函数的返回值,但transform
会将该返回值复制到另一个区间中。
transform
有两个版本,第一个版本将外部函数套用于[first, last)
上,第二个版本则将外部函数套用于两个大小相等的区间[first1, last1)
与[first2, first2+(last1-first1))
上,也就是说,第一个版本的外部函数需要一个参数,第二个版本的外部函数需要两个函数。
版本一会对每一个迭代器i
执行pred(*i)
,并将运算结果赋值给*result
,返回值为result+(last-first)
版本二会对每一个区间的迭代器i1
和i2
执行pred(*i1, *i2)
,并将运算结果赋值给*result
,返回值为result+(last1-first1)
特别的,transform
可以被用来原地更改序列,它允许first
和result
是同一个迭代器
复杂度:线性O(n)
,执行last1 - first1
次交换动作
例子:
// 将原区间值加10,并返回加后数值的相反数
int unaryFunc(int& a) {
a += 10;
return -a;
}
// 将区间一元素值加5,区间二元素值减5,并将加减后的值相加后返回
int binaryFunc(int& a, int& b) {
a += 5;
b -= 5;
return a + b;
}
// 原区间元素不变,返回相反数
int indentityFunc(int a) {
return -a;
}
// 方便输出
void printArr(const char* str, int* arr, const int a) {
cout << str << ": ";
for(int i = 0; i != a; ++i)
cout << arr[i] << " ";
cout << endl;
}
int main() {
constexpr int a = 5;
int arr1[] = {0, 1, 2, 3, 4};
int arr2[] = {0, 1, 2, 3, 4};
int arr3[] = {5, 6, 7, 8, 9};
int result1[a];
int result2[a];
transform(arr1, arr1+a, result1, unaryFunc);
printArr("arr1", arr1, a);
printArr("resulr1", result1, a);
transform(arr2, arr2+a, arr3, result2, binaryFunc);
printArr("arr2", arr2, a);
printArr("arr3", arr3, a);
printArr("resulr2", result2, a);
transform(arr1, arr1+a, arr1, indentityFunc);
printArr("arr1", arr1, a);
return 0;
}
输出:
arr1: 10 11 12 13 14
resulr1: -10 -11 -12 -13 -14
arr2: 5 6 7 8 9
arr3: 0 1 2 3 4
resulr2: 5 7 9 11 13
arr1: -10 -11 -12 -13 -14
替换元素
replace
用法:replace(first, last, old_value, new_value)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
void replace(ForwardIterator first, ForwardIterator last,
const T& old_value, const T& new_value);
该算法会遍历区间[first, last)
中的每个元素,会将该区间每个old_vlaue
替换为new_value
,与old_value
值不相等的元素不会受影响。
复杂度:线性O(n)
,执行last - first
次比较动作 ,最多执行last - first
次赋值动作
例子:
int main() {
constexpr int a = 5;
int arr[a] = {0, 1, 2, 3, 1};
replace(arr, arr+a, 1, 100);
for(auto x : arr) {
cout << x << " ";
}
return 0;
}
输出:
0 100 2 3 100
replace_if
用法:replace_if(first, last, pred, new_value)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Predicate, class T>
void replace_if(ForwardIterator first, ForwardIterator last,
Predicate pred, const T& new_value);
该算法会遍历区间[first, last)
中的每个元素,会将该区间每个满足pred
的元素替换为new_value
,不满足pred
的元素不会受影响。
复杂度:线性O(n)
,执行last - first
次比较动作 ,最多执行last - first
次赋值动作
例子:
class cmp {
public:
bool operator()(int x) {
return (x % 2 == 0);
}
};
int main() {
constexpr int a = 5;
int arr[a] = {0, 1, 2, 3, 4};
replace_if(arr, arr+a, cmp(), 55);
for(auto x : arr) {
cout << x << " ";
}
return 0;
}
输出:
55 1 55 3 55
replace_copy
用法:replace_copy(first, last, result, old_value, new_value)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator, class T>
OutputIterator replace_copy(InputIterator first, InputIterator last,
OutputIterator result, const T& old_value,
const T& new_value);
该算法会将区间[first, last)
的元素复制到[result, result+(last-first))
中复制过程中会将old_value
以new_value
替代, 原区间[first, last)
不会被改动,该函数会返回result+(last-first)
复杂度:线性O(n)
,执行last - first
次比较动作 ,最多执行last - first
次赋值动作
例子:
int main() {
constexpr int a = 5;
int arr1[a] = {0, 1, 2, 3, 1};
int arr2[a];
replace_copy(arr1, arr1+a, arr2, 1, 100);
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
cout << endl << "arr2: ";
for(auto x : arr2) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 0 1 2 3 1
arr2: 0 100 2 3 100
replace_copy_if
用法:replace_copy_if(first, last, result, pred, new_value)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator,
class Predicate, class T>
OutputIterator replace_copy_if(InputIterator first, InputIterator last,
OutputIterator result, Predicate pred,
const T& new_value);
该算法会将区间[first, last)
的元素复制到[result, result+(last-first))
中,复制过程中会将该区间每个满足pred
的元素替换为new_value
, 原区间[first, last)
不会被改动,该函数会返回result+(last-first)
复杂度:线性O(n)
,执行last - first
次比较动作 ,最多执行last - first
次赋值动作
例子:
int main() {
constexpr int a = 5;
int arr1[a] = {0, 1, 2, 3, 4};
int arr2[a];
replace_copy_if(arr1, arr1+a, arr2, cmp(), 100);
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
cout << endl << "arr2: ";
for(auto x : arr2) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 0 1 2 3 4
arr2: 100 1 100 3 100
填充
fill
用法:fill(first, last, value)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
void fill(ForwardIterator first, ForwardIterator last, const T& value);
该算法会将value
值赋值给[first, last)
的每个元素,即执行*i = value
,但也不可用于容器的插入
复杂度:线性O(n)
,执行last - first
次赋值动作
例子:
int main() {
constexpr int a = 5;
int arr1[a] = {0, 1, 2, 3, 4};
fill(arr1, arr1+a, 100);
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 100 100 100 100 100
fill_n
用法:fill_n(first, n, value)
定义头文件:<algorithm>
函数原型:
template <class OutputIterator, class Size, class T>
void fill(OutputIterator first, Size n, const T& value);
该算法会将value
值赋值给[first, first+n)
的每个元素
复杂度:线性O(n)
,执行last - first
次赋值动作
例子:
int main() {
constexpr int a = 5;
int arr1[a] = {0, 1, 2, 3, 4};
fill_n(arr1, 3, 100);
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 100 100 100 3 4
generate
用法:generate(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Generator>
void generate(ForwardIterator first, ForwardIterator last,
Generator pred);
该算法会将调用不需要任何参数的外部函数,并将外部函数的返回值赋值给[first, last)
中的每一个元素
该函数会调用first-last
次外部函数,如果只想调用一次外部函数,并将其结果赋值给区间中的每一个元素,可以使用fill
函数
复杂度:线性O(n)
,执行last - first
次赋值动作
例子:
class cmp {
public:
static int x;
int operator()() {
return x++;
}
};
int cmp::x = 10;
int main() {
constexpr int a = 5;
int arr1[a];
generate(arr1, arr1+a, cmp());
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 10 11 12 13 14
generate_n
用法:generate_n(first, n, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Size, class Generator>
void generate(ForwardIterator first, Size n, Generator pred);
该算法会将调用不需要任何参数的外部函数,并将外部函数的返回值赋值给[first, first+n)
中的每一个元素
该函数会调用n
次外部函数,如果只想调用一次外部函数,并将其结果赋值给区间中的每一个元素,可以使用fill_n
函数
复杂度:线性O(n)
,执行n
次赋值动作
例子:
class cmp {
public:
static int x;
int operator()() {
return x++;
}
};
int cmp::x = 10;
int main() {
constexpr int a = 5;
int arr1[a] = {0};
generate(arr1, arr1+3, cmp());
cout << "arr1: ";
for(auto x : arr1) {
cout << x << " ";
}
return 0;
}
输出:
arr1: 10 11 12 0 0
移除元素
remove
用法:remove(first, last, value)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last,
const T& value);
remove
函数不可能摧毁任何迭代器或者改变first
到last
的距离。例如有一个int A[10]
数组,如果有remove(A, A+10, 3)
,实际上remove
函数不会改变A
数组的元素个数,A+10
也永远会指向A
之后第十个元素的位置。该算法不会直接作用于range
身上,而是作用于迭代器上,所以不会改变容器的大小。
实际上remove
函数会返回一个新的迭代器new_last
,而该容器的end()
所指不变,使得[first, new_last)
内的元素都不等于value
。也就是所remove
函数是稳定的,意思是区间左端元素的相对位置不变。
复杂度:线性O(n)
,执行last-first
次比较动作
例子:
int main() {
vector<int> vec = {1, 2, 3, 1, 4, 7, 1, 5, 9};
auto la = remove(vec.begin(), vec.end(), 1);
for(auto it = vec.begin(); it != la; ++it)
cout << *it << " ";
cout << endl;
for(auto it = vec.begin(); it != vec.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
2 3 4 7 5 9
2 3 4 7 5 9 1 5 9
remove_if
用法:remove_if(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predcite pred);
remove_if
函数和remove
函数一样不会摧毁任何迭代器或者改变first
到last
的距离,也不会改变容器的大小。返回情况也与remove
相同。
唯一不同的便是remove
是移除值等于value
的元素,而remove_if
是移除条件符合pred
的元素。更具一般性。
复杂度:线性O(n)
,执行last-first
次pred
动作
例子:
// 移除能被三整除的元素
bool comp(int x) {
return x % 3 == 0;
}
int main() {
vector<int> vec = {1, 2, 3, 1, 4, 7, 1, 5, 9};
auto la = remove_if(vec.begin(), vec.end(), comp);
for(auto it = vec.begin(); it != la; ++it)
cout << *it << " ";
cout << endl;
for(auto it = vec.begin(); it != vec.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
1 2 1 4 7 1 5
1 2 1 4 7 1 5 5 9
remove_copy
用法:remove_copy(first, last, result, value)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator, class T>
OutputIterator remove_copy(InputIterator first, InputIterator last,
OutputIterator result, const T& value);
remove_copy
函数和remove
函数不一样的地方在于,remove
函数在自身容器内进行移除,而remove_copy
自身容器内元素不变,会将移除后的结果放在result
结果中,而返回值new_last
则是返回该复制的区间的尾端,即移除结果会放在区间[result, new_last)
中。
该行为与remove
相同,也是稳定的,即被复制元素相对位置不变。
复杂度:线性O(n)
,执行last-first
次比较动作,最多执行last-first
次赋值操作
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 1, 4, 7, 1, 5, 9};
vector<int> vec2(9);
auto la = remove_copy(vec1.begin(), vec1.end(), vec2.begin(), 1);
cout << "复制容器:";
for(auto it = vec2.begin(); it != la; ++it)
cout << *it << " ";
cout << endl;
cout << "原容器:";
for(auto it = vec1.begin(); it != vec1.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
复制容器:2 3 4 7 5 9
原容器:1 2 3 1 4 7 1 5 9
remove_copy_if
用法:remove_copy_if(first, last, result, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator, class Predicate>
OutputIterator remove_copy_if(InputIterator first, InputIterator last,
OutputIterator result, Predicate pred);
remove_copy_if
函数和remove_copy
函数一样不会摧毁任何迭代器或者改变first
到last
的距离,也不会改变容器的大小。返回情况也与remove_copy
相同。
唯一不同的便是remove_copy
是移除值等于value
的元素,而remove_copy_if
是移除条件符合pred
的元素。更具一般性。
复杂度:线性O(n)
,执行last-first
次pred
动作,最多执行last-first
次赋值操作
例子:
// 移除能被三整除的元素
bool comp(int x) {
return x % 3 == 0;
}
int main() {
vector<int> vec1 = {1, 2, 3, 1, 4, 7, 1, 5, 9};
vector<int> vec2(9);
auto la = remove_copy_if(vec1.begin(), vec1.end(), vec2.begin(), comp);
cout << "复制容器:";
for(auto it = vec2.begin(); it != la; ++it)
cout << *it << " ";
cout << endl;
cout << "原容器:";
for(auto it = vec1.begin(); it != vec1.end(); ++it)
cout << *it << " ";
return 0;
}
输出:
复制容器:1 2 1 4 7 1 5
原容器:1 2 3 1 4 7 1 5 9
unique
用法:unique(first, last)
或unique(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
ForwardIterator unique(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class BinaryPredicate>
ForwardIterator unique(ForwardIterator first, ForwardIterator last,
BinaryPredicate pred);
该函数可以移除重复的元素,当[first, last)
内遇到相连元素群出现,unique
便会移除该群的第一个以外的所有元素。如果想以这个函数移除所有重复元素,必须使所有重复函数相邻,得靠unique
和sort
搭配使用。
该函数会返回一个迭代器new_last
,使得[first, new_last)
内元素都不相邻,所以该算法是稳定的。
该函数有两个版本,第一个版本以operator==
比较,而第二版本以pred()
进行比较,第二个版本比第一个版本更具一般性。
复杂度:线性O(n)
,执行last-first-1
次动作。
例子:
// 移除能被三整除的元素
bool comp(int x, int y) {
return x % 3 == 0 && y % 3 == 0;
}
int main() {
vector<int> vec1 = {1, 2, 1, 1, 1, 7, 5, 5, 9};
vector<int> vec2 = {1, 2, 3, 9, 6, 7, 4, 5, 9};
auto la1 = unique(vec1.begin(), vec1.end());
auto la2 = unique(vec2.begin(), vec2.end(), comp);
for(auto it = vec1.begin(); it != la1; ++it)
cout << *it << " ";
cout << endl;
for(auto it = vec2.begin(); it != la2; ++it)
cout << *it << " ";
return 0;
}
输出:
1 2 1 7 5 9
1 2 3 7 4 5 9
unique_copy
用法:unique_copy(first, last, result)
或unique_copy(first, last, result, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class OutputIterator>
OutputIterator unique_copy(InputIterator first, InputIterator last,
OutputIterator result);
template <class InputIterator, class OutputIterator, class BinaryPredicate>
OutputIterator unique_copy(InputIterator first, InputIterator last,
OutputIterator result, BinaryPredicate pre);
该函数与unique
的区别跟remove
与remove_copy
的区别一样,不会改变原容器,而是将移除相邻重复的元素后的区间放到result
中,返回值为迭代器new_last
,即移除相邻重复元素后的区间为[result, new_last)
该函数有两个版本,第一个版本以operator==
比较,而第二版本以pred()
进行比较,第二个版本比第一个版本更具一般性。
复杂度:线性O(n)
,执行last-first
次比较动作,最多执行last-first
次复制动作。
例子:
// 移除能被三整除的元素
bool comp(int x, int y) {
return x % 3 == 0 && y % 3 == 0;
}
int main() {
vector<int> vec1 = {1, 2, 1, 1, 1, 7, 5, 5, 9};
vector<int> vec2 = {1, 2, 3, 9, 6, 7, 4, 5, 9};
vector<int> vec3(10);
vector<int> vec4(10);
auto la1 = unique_copy(vec1.begin(), vec1.end(), vec3.begin());
auto la2 = unique_copy(vec2.begin(), vec2.end(), vec4.begin(), comp);
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto x : vec2)
cout << x << " ";
cout << endl;
cout << "vec3:";
for(auto it = vec3.begin(); it != la1; ++it)
cout << *it << " ";
cout << endl;
cout << "vec4:";
for(auto it = vec4.begin(); it != la2; ++it)
cout << *it << " ";
cout << endl;
return 0;
}
输出:
vec1:1 2 1 1 1 7 5 5 9
vec2:1 2 3 9 6 7 4 5 9
vec3:1 2 1 7 5 9
vec4:1 2 3 7 4 5 9
排列
reverse
用法:reverse(first, last)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator>
void reverse(BidirectionalIterator first, BidirectionalIterator last);
该算法会将区间[first, last)
的内容就地反转,该反转指迭代器所指的元素反转,而不是迭代器自身反转。
复杂度:线性O(n)
,调用swap()
函数(last-first)/2
次。
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << "原容器:";
for(auto x : vec)
cout << x << " ";
cout << endl;
reverse(vec.begin(), vec.end());
cout << "反转后:";
for(auto x : vec)
cout << x << " ";
cout << endl;
return 0;
}
输出:
原容器:1 2 3 4 5 6 7 8 9
反转后:9 8 7 6 5 4 3 2 1
reverse_copy
用法:reverse_copy(first, last, result)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator, class OutputIterator>
OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last,
OutputIterator result);
该算法会将区间[first, last)
的内容反转,并将反转后的结果放在区间[result, result+(last-first))
中,该元素返回值为迭代器result+(last-first)
复杂度:线性O(n)
,执行last-first
次赋值操作。
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> vec2(9);
auto la = reverse_copy(vec1.begin(), vec1.end(), vec2.begin());
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto it = vec2.begin(); it != la; ++it)
cout << *it << " ";
cout << endl;
return 0;
}
输出:
vec1:1 2 3 4 5 6 7 8 9
vec2:9 8 7 6 5 4 3 2 1
rotate
用法:rotate(first, middle, last)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last);
该算法会将区间[first, last)
的元素加以旋转,它会将middle
处的元素移到first
处,将middle+1
处的元素移到first+1
处……更简单的理解便是:它会将区间[first, middle)
和[middle, last)
互换。
既然是两个区间互换,为什么不用swap_range
呢?原因是swap_range
只能交换两个长度相同的区间,而rotate
能交换两个长度不同的相邻区间。
复杂度:线性O(n)
,最多调用swap
函数last-first
次。
例子:
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << "原容器:";
for(auto x : vec)
cout << x << " ";
cout << endl;
rotate(vec.begin(), vec.begin()+3, vec.end());
cout << "旋转后:";
for(auto x : vec)
cout << x << " ";
cout << endl;
return 0;
}
输出:
原容器:1 2 3 4 5 6 7 8 9
旋转后:4 5 6 7 8 9 1 2 3
rotate_copy
用法:rotate_copy(first, middle, last, result)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class OutputIterator>
OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle,
ForwardIterator last, OutputIterator result);
该算法与rotate
唯一不同在于,rotate
是原地旋转,而该函数会把旋转后的结果放在区间[reslt, result+(last-first))
中,该函数返回值为迭代器result+(last-first)
复杂度:线性O(n)
,执行last-first
次赋值操作。
例子:
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> vec2(9);
auto la = rotate_copy(vec1.begin(), vec1.begin()+3, vec1.end(), vec2.begin());
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto x : vec2)
cout << x << " ";
cout << endl;
return 0;
}
输出:
vec1:1 2 3 4 5 6 7 8 9
vec2:4 5 6 7 8 9 1 2 3
next_permutation
用法:next_permutation(first, last)
或next_permutation(first, last, pres)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator>
bool next_permutation(BidirectionalIterator first,
BidirectionalIterator last);
template <class BidirectionalIterator, class StrictWeakOrdering>
bool next_permutation(BidirectionalIterator first,
BidirectionalIterator last,
StrictWeakOrdering pred);
前面有介绍过函数lexicographical_compare
,这个函数是按照字典排序来比较两个区间,而我们现在要介绍的这个函数也是以字典排序为基础的,会以字典排序对原区间原地更改为下一个较大的排序顺序
该函数返回值为布尔类型,如果有下一个更大的序列则返回true
,若没有则返回false
并将原序列以最小排列顺序排好。
该函数有两个版本,第一版本以operator<
进行比较,第二个版本以pred
进行比较。
复杂度:线性O(n)
,至多调用swap
函数(last-first)/2
次。
例子:
void printVec(const vector<int>& vec) {
static int i = 0;
cout << "vec" << i++ << ":";
for(auto x : vec)
cout << x << " ";
cout << endl;
}
int main() {
vector<int> vec = {1, 2, 3};
while(next_permutation(vec.begin(), vec.end())) {
printVec(vec);
}
return 0;
}
输出:
vec0:1 3 2
vec1:2 1 3
vec2:2 3 1
vec3:3 1 2
vec4:3 2 1
prev_permutation
用法:prev_permutation(first, last)
或prev_permutation(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator>
bool prev_permutation(BidirectionalIterator first,
BidirectionalIterator last);
template <class BidirectionalIterator, class StrictWeakOrdering>
bool prev_permutation(BidirectionalIterator first,
BidirectionalIterator last,
StrictWeakOrdering pred);
该函数与next_permutation
差不多,差别在于next_permutation
以下一个更大的序列进行排序,而prev_permutation
以下一个更小的需例如进行排序。
同样的,该函数返回值为布尔类型,如果有下一个更小的序列则返回true
,若没有则返回false
并将原序列以最大排列顺序排好。
该函数有两个版本,第一版本以operator>
进行比较,第二个版本以pred
进行比较。
复杂度:线性O(n)
,至多调用swap
函数(last-first)/2
次。
例子:
void printVec(const vector<int>& vec) {
static int i = 0;
cout << "vec" << i++ << ":";
for(auto x : vec)
cout << x << " ";
cout << endl;
}
int main() {
vector<int> vec = {3, 2, 1};
while(prev_permutation(vec.begin(), vec.end())) {
printVec(vec);
}
return 0;
}
输出:
vec0:3 1 2
vec1:2 3 1
vec2:2 1 3
vec3:1 3 2
vec4:1 2 3
分割
partition
用法:partition(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator, class Predicate>
BidirectionalIterator partition(BidirectionalIterator first,
BidirectionalIterator last,
Predicate pred);
该算法会根据pred
函数重新排列[first, last)
的元素,使得满足pred
的元素排在不满足pred
的元素之前。
该函数的必然结果是:[first, last)
内会存在一个迭代器middle
,使得[first, middle)
内每个元素都满足pred
,而区间[middle, last)
内每个元素都不满足pred
,该函数的返回值为迭代器middle
,但该函数不会对元素顺序进行任何保证。
复杂度:线性O(n)
,调用pred
共last-first
次,至多调用swap
函数(last-first)/2
次。
例子:
bool comp(int x) {
return x % 2 == 0;
}
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto middle = partition(vec.begin(), vec.end(), comp);
cout << "all:";
for(auto it = vec.begin(); it != vec.end(); ++it)
cout << *it << " ";
cout << endl;
cout << "first-middle:";
for(auto it = vec.begin(); it != middle; ++it)
cout << *it << " ";
cout << endl;
cout << "middle-last:";
for(auto it = middle; it != vec.end(); ++it)
cout << *it << " ";
cout << endl;
}
输出:
all:8 2 6 4 5 3 7 1 9
first-middle:8 2 6 4
middle-last:5 3 7 1 9
stable_partition
用法:partition(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class Predicate>
ForwardIterator partition(ForwardIterator first, ForwardIterator last,
Predicate pred);
该算法与partition
非常类似,唯一不同在于该算法是稳定的,即能保持元素的相对位置。但相较于partition
速度较慢。
复杂度:线性O(n)
,调用pred
共last-first
次,至多调用swap
函数(last-first)/2
次。
例子:
bool comp(int x) {
return x % 2 == 0;
}
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto middle = stable_partition(vec.begin(), vec.end(), comp);
cout << "all:";
for(auto it = vec.begin(); it != vec.end(); ++it)
cout << *it << " ";
cout << endl;
}
输出:
all:2 4 6 8 1 3 5 7 9
随机抽样与重排
random_shuffle
用法:random_shuffle(first, last)
或random_shuffle(first, last, rand)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void random_shuffle(RandomAccessIterator first,
RandomAccessIterator last);
template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(RandomAccessIterator first,
RandomAccessIterator last,
RandomNumberGenerator& rand);
random_shuffle
是随机排序,意味着他会从n!
中可能的元素排列顺序中随机选出一种,该函数有两个版本,区别在于乱数的获取,版本一使用了内部乱数生产器,版本二使用随机数生成器,传递方式是引用传递,而不是值传递,因为该生成器具有局部状态,每次被调用是都会改变。
复杂度:线性O(n)
,调用swap
函数last-first-1
次。
例子:
int myRand(int n) {
return rand() % n;
}
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
random_shuffle(vec.begin(), vec.end());
for(auto x : vec)
cout << x << " ";
cout << endl;
random_shuffle(vec.begin(), vec.end(), myRand);
for(auto x : vec)
cout << x << " ";
cout << endl;
return 0;
}
输出:
9 2 7 3 1 6 8 4 5
1 4 7 9 2 5 8 6 3
数值算法
accumulate
用法:accumulate(first, last, init)
或accumulate(first, last, init, pred)
定义头文件:<numeric>
函数原型:
template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);
template <class InputIterator, class T, class BinaryFunction>
T accumulate(InputIterator first, InputIterator last,
T init, BinaryFunction pred);
该函数为总和运算的一般类型,他可以计算init
和[first, last)
内的元素总和,如果只想计算区间[first, last)
的总和,应该将init
设为0
版本一的计算执行operator+
进行计算,即result = result + *i
,而版本二则使用pred
来进行计算, 即result = pred(result, *i)
。
复杂度:线性O(n)
,调用双参数运算last-first
次。
例子:
// 用accumulate模拟阶乘
int op_pred(int x, int y) {
return x * y;
}
int main() {
vector<int> vec = {1, 2, 3, 4};
cout << accumulate(vec.begin(), vec.end(), 0) << endl;
cout << accumulate(vec.begin(), vec.end(), 1, op_pred) << endl;
return 0;
}
输出:
10
24
inner_product
用法:inner_product(first1, last1, first2, init)
或inner_product(first1, last1, first2, init, pred1, pred2)
定义头文件:<numeric>
函数原型:
template <class InputIterator1, class InputIterator2, class T>
T inner_product(InputIterator1 first1, InputIterato1r last1,
InputIterator2 first2, T init);
template <class InputIterator1, class InputIterator2, class T,
class BinaryFunction1, class BinaryFunction2>
T inner_product(InputIterator1 first1, InputIterato1r last1,
InputIterator2 first2, T init,
BinaryFunction1 binary_op1, BinaryFunction2 binary_op2);
该函数能计算[first1, last1)
和[first2, first2+(last1-first1))
的一般化内积。
版本一的计算执行operator+
和operator*
进行计算,即result = result + (*i) * *(first2 + (i - first1))
,而版本二则使用pred
来进行计算,即result = pred1(result, pred2(*i, *(first2 + (i - first1))))
。
复杂度:线性O(n)
,调用双参数运算last1-first1
次。
例子:
int main() {
vector<int> vec1 = {2, 3, 4};
vector<int> vec2 = {1, 2, 3};
cout << inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0) << endl;
return 0;
}
输出:
20
partial_sum
用法:partial_sum(first, last, result)
或partial_sum(first, last, result, pred)
定义头文件:<numeric>
函数原型:
template <class InputIterator, class OutputIterator>
OutputIterator partial_sum(InputIterator first, InputIterator last,
OutputIterator result);
template <class InputIterator, class OutputIterator, class BinaryFunction>
OutputIterator partial_sum(InputIterator first, InputIterator last,
OutputIterator result, BinaryFunction pred)
该函数能用来计算部分总和,它会将*first
赋值给*result
,将*first
和*(first+1)
的和赋值给*(result+1)
……,此时应该注意,result
和first
可以相等,即可以原地计算该区间的部分总和。该函数返回输出迭代器的尾端,即result+(last-first)
第一版本使用operator+
进行运算,即sum = sum + *i
,而第二版本则使用pred
进行运算,即sum = pred(sum, *i)
,显然,第二个版本更具有一般性。
复杂度:线性O(n)
,调用双参数运算last-first-1
次。
例子:
// 模拟累乘
int op_pred(int x, int y) {
return x * y;
}
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> vec2(9);
vector<int> vec3(9);
auto la1 = partial_sum(vec1.begin(), vec1.end(), vec2.begin());
auto la2 = partial_sum(vec1.begin(), vec1.end(), vec3.begin(), op_pred);
cout << "vec1:";
for(auto it = vec1.begin(); it != vec1.end(); ++it)
cout << *it << " ";
cout << endl;
cout << "vec2:";
for(auto it = vec2.begin(); it != la1; ++it)
cout << *it << " ";
cout << endl;
cout << "vec3:";
for(auto it = vec3.begin(); it != la2; ++it)
cout << *it << " ";
cout << endl;
return 0;
}
输出:
vec1:1 2 3 4 5 6 7 8 9
vec2:1 3 6 10 15 21 28 36 45
vec3:1 2 6 24 120 720 5040 40320 362880
adjacent_difference
用法:adjacent_difference(first, last, result)
或adjacent_difference(first, last, result, pred)
定义头文件:<numeric>
函数原型:
template <class InputIterator, class OutputIterator>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result);
template <class InputIterator, class OutputIterator, class BinaryFunction>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result, BinaryFunction pred);
该算法可以用来计算[first, last)
中相邻元素的差值,也就是说它会将*first
赋值给*result
,并将[first+1, last)
内每个迭代器i
,会将*i
与*(i-1)
的差赋值给*(result+(i-first))
,同样的,result
可以与first
相等,因此可以原地进行计算差额。该函数返回输出迭代器的尾端,即result+(last-first)
第一版本使用operator-
进行运算,即*i - *(i - 1)
,而第二版本则使用pred
进行运算,即pred(*i, *(i - 1))
,显然,第二个版本更具有一般性。
特别注意,该函数与partial_sum
可为相反运算。
复杂度:线性O(n)
,调用双参数运算last-first-1
次。
例子:
// 模拟相乘
int op_pred(int x, int y) {
return x * y;
}
int main() {
vector<int> vec1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int> vec2(9);
vector<int> vec3(9);
auto la1 = adjacent_difference(vec1.begin(), vec1.end(), vec2.begin());
auto la2 = adjacent_difference(vec1.begin(), vec1.end(), vec3.begin(), op_pred);
cout << "vec1:";
for(auto it = vec1.begin(); it != vec1.end(); ++it)
cout << *it << " ";
cout << endl;
cout << "vec2:";
for(auto it = vec2.begin(); it != la1; ++it)
cout << *it << " ";
cout << endl;
cout << "vec3:";
for(auto it = vec3.begin(); it != la2; ++it)
cout << *it << " ";
cout << endl;
return 0;
}
输出:
vec1:1 2 3 4 5 6 7 8 9
vec2:1 1 1 1 1 1 1 1 1
vec3:1 2 6 12 20 30 42 56 72
排序和查找
对某个区间排序
sort
用法:sort(first, last)
或sort(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void sort(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering pred);
这个函数大家想必很熟悉了,可以将[first, last)
内的元素非递减排序,这个函数不一定是一个稳定函数,如果*i
和*j
等价,不保证排序后这两个元素的相对位置不变。
第一版本使用operator<
进行比较,而第二版本则使用pred
进行比较,显然,第二个版本更具有一般性。
复杂度:平均O(n logn)
,最坏O(n^2)
,其中n
为last-first
。
例子:
bool comp(int x, int y) {
return x > y;
}
int main() {
vector<int> vec1 = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
vector<int> vec2 = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
sort(vec1.begin(), vec1.end());
sort(vec2.begin(), vec2.end(), comp);
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto x : vec2)
cout << x << " ";
cout << endl;
return 0;
}
输出:
vec1:0 1 2 3 4 5 6 6 7 8
vec2:8 7 6 6 5 4 3 2 1 0
stable_sort
用法:stable_sort(first, last)
或stable_sort(first, last, pred)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void stable_sort(RandomAccessIterator first, RandomAccessIterator last,
StrictWeakOrdering pred);
这个函数与sort
极其相似,有两个与其不同之处,第一,这两个算法的运行复杂度不同,通常来说sort
会更快,第二,该算法是稳定的,如果*i
和*j
等价,能保证排序后这两个元素的相对位置不变。
第一版本使用operator<
进行比较,而第二版本则使用pred
进行比较,显然,第二个版本更具有一般性。
复杂度:平均O(n logn)
,最坏O(n (logn)^2)
,其中n
为last-first
。
例子:
bool comp(int x, int y) {
return x > y;
}
int main() {
vector<int> vec1 = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
vector<int> vec2 = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
stable_sort(vec1.begin(), vec1.end());
stable_sort(vec2.begin(), vec2.end(), comp);
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto x : vec2)
cout << x << " ";
cout << endl;
return 0;
}
输出:
vec1:0 1 2 3 4 5 6 6 7 8
vec2:8 7 6 6 5 4 3 2 1 0
partial_sort
用法:partial_sort(first, middle, last)
或partial_sort(first, middle, last, pred)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void partial_sort(RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void partial_sort(RandomAccessIterator first,
RandomAccessIterator middle,
RandomAccessIterator last,
StrictWeakOrdering comp);
该函数会使middle-first
个最小元素以不递减顺序排序,并包含于[middle, last)
中,而其他的last-middle
个元素则安放于[middle last)
中,无任何特定的顺序。
第一版本使用operator<
进行比较,而第二版本则使用pred
进行比较,显然,第二个版本更具有一般性。
复杂度:平均(last-first) log(middle-first)
次比较动作。
例子:
int main() {
vector<int> vec = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
partial_sort(vec.begin(), vec.begin()+4, vec.end());
cout << "vec:";
for(auto x : vec)
cout << x << " ";
cout << endl;
return 0;
}
输出:
vec:0 1 2 3 8 6 7 5 4 6
partial_sort_copy
用法:partial_sort_copy(first, last, result_first, result_last)
或partial_sort_copy(first, last, result_first, result_last, pred)
定义头文件:<algorithm>
函数原型:
template <class InputIterator, class RandomAccessIterator>
void partial_sort_copy(InputIterator first, InputIterator last,
RandomAccessIterator result_first,
RandomAccessIterator result_last);
template <class InputIterator, class RandomAccessIterator, class StrictWeakOrdering>
void partial_sort_copy(InputIterator first, InputIterator last,
RandomAccessIterator result_first,
RandomAccessIterator result_last,
StrictWeakOrdering comp);
可以由名称看得出来,该函数是partial_sort
的复制版本,但它并不是直接在partial_sort
后直接copy
,而是像partial_sort
运用[first, middle)
一样运用[result_first, result_last)
。该函数是从[first, last)
中复制前n
个元素到[result_first, result_last)
中,n
取决于两个区间的最小值,被复制的元素会以非递减顺序排序。
复杂度:平均(last-first) log(n)
次比较动作。
例子:
int main() {
vector<int> vec1 = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
vector<int> vec2(5);
partial_sort_copy(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
cout << "vec1:";
for(auto x : vec1)
cout << x << " ";
cout << endl;
cout << "vec2:";
for(auto x : vec2)
cout << x << " ";
cout << endl;
return 0;
}
输出:
vec1:5 1 8 6 3 4 7 2 0 6
vec2:0 1 2 3 4
nth_element
用法:nth_element(first, nth, last)
或nth_element(first, nth, last, comp)
定义头文件:<algorithm>
函数原型:
template <class RandomAccessIterator>
void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
RandomAccessIterator last);
template <class RandomAccessIterator, class StrictWeakOrdering>
void nth_element(RandomAccessIterator first, RandomAccessIterator nth,
RandomAccessIterator last, StrictWeakOrdering comp);
该函数与partial_sort
一样会对区间中的元素进行部分排序,使得nth
所指的元素与整个[first, last)
排序后的同一位置的元素相同,同时nth
也可以用作分割,它能保证[nth, last)
内没有一个元素小于[first, nth)
内的元素。
但该函数与partial_sort
不同的地方在于,nth_element
不保证[first, nth)
或[nth, last)
都会被排序,它只保证[first, nth)
的元素不大于[nth, last)
内的元素。
第一版本使用operator<
进行比较,而第二版本则使用comp
进行比较,显然,第二个版本更具有一般性。
复杂度:平均O(n)
,与last-first
成线性关系。
例子:
int main() {
vector<int> vec = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
nth_element(vec.begin(), vec.begin()+4, vec.end());
for(auto x : vec)
cout << x << " ";
return 0;
}
输出:
1 0 2 3 4 5 7 6 8 6
is_sorted
用法:is_sorted(first, last)
或is_sorted(first, last, comp)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator>
bool is_sorted(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class StrictWeakOrdering>
bool is_sorted(ForwardIterator first, ForwardIterator last,
StrictWeakOrdering comp);
该函数正如其名,只用来判断区间是否已经有序,如果[first, last)
有序,则会返回true
,否则返回false
。
第一版本使用operator<
进行比较,而第二版本则使用comp
进行比较,显然,第二个版本更具有一般性。
复杂度:平均O(n logn)
,最坏O(n (logn)^2)
,其中n
为last-first
。
例子:
bool comp(int x, int y) {
return x > y;
}
int main() {
vector<int> vec = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
cout << boolalpha << is_sorted(vec.begin(), vec.end()) << " ";
cout << boolalpha << is_sorted(vec.begin(), vec.end(), comp) << endl;
sort(vec.begin(), vec.end());
cout << boolalpha << is_sorted(vec.begin(), vec.end()) << " ";
cout << boolalpha << is_sorted(vec.begin(), vec.end(), comp) << endl;
sort(vec.begin(), vec.end(), comp);
cout << boolalpha << is_sorted(vec.begin(), vec.end()) << " ";
cout << boolalpha << is_sorted(vec.begin(), vec.end(), comp) << endl;
return 0;
}
输出:
false false
true false
false true
二分查找
binary_search
用法:binary_search(fitst, last, value)
或binary_search(first, last, value, comp)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last,
const T& value);
template <class ForwardIterator, class T, class StrictWeakOrdering>
bool binary_search(ForwardIterator first, ForwardIterator last,
const T& value, StrictWeakOrdering comp);
该函数是二分查找的一个版本,他会从已排序的区间中寻找元素value
,如果区间中有等价于value
的元素,则会返回true
, 否则返回false
。
该函数第一个版本采用operator<
进行比较,更加准确的说是:在区间中存在一个迭代器i
使得*i < value
和value < *i
都不为真,则返回true
,同样的,第二个版本使用comp
进行比较,使得comp(*i, value)
和comp(value, *i)
都不为真,则返回true
。
复杂度:至多log(last-first)+2
次比较
例子:
int main() {
vector<int> vec = {5, 1 ,8, 6, 3, 4, 7, 2, 0, 6};
sort(vec.begin(), vec.end());
cout << boolalpha << binary_search(vec.begin(), vec.end(), 3);
return 0;
}
输出:
true
lower_bound
用法:lower_bound(first, last, value)
或lower_bound(first, last, value, comp)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
const T& value);
template <class ForwardIterator, class T, class StrictWeakOrdering>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
const T& value, StrictWeakOrdering comp);
该函数与binary_search
一样,会从已排序的区间寻找元素value
,如果找到等价于value
的元素,则lower_bound
会返回一个迭代器指向其中的第一个元素,如果没有这样的元素,则会返回假设该元素存在的话会出现的位置,也就是说,会返回第一个不小于value
的元素。
第一版本采用operator<
进行比较,使得存在一个迭代器使得[first, i)
中每个元素都小于value
,第二版本采用comp
进行比较,使得[first, i)
中每个迭代器都满足comp(*j, value)
为真。
复杂度:至多log(last-first)+1
次比较
例子:
int main() {
vector<int> vec = {0, 1, 2, 3, 4, 6, 6, 7, 8};
auto it1 = lower_bound(vec.begin(), vec.end(), 4);
auto it2 = lower_bound(vec.begin(), vec.end(), 5);
for(; it1 != vec.end(); ++it1)
cout << *it1 << " ";
cout << endl;
for(; it2 != vec.end(); ++it2)
cout << *it2 << " ";
return 0;
}
输出:
4 6 6 7 8
6 6 7 8
upper_bound
用法:upper_bound(first, last, value)
或upper_bound(first, last, value, comp)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
const T& value);
template <class ForwardIterator, class T, class StrictWeakOrdering>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
const T& value, StrictWeakOrdering comp);
该函数与lower_bound
类似,只不过会返回一个迭代器指向其中的最后一个与value
等价的元素。
第一版本采用operator<
进行比较,使得存在一个迭代器使得[first, i)
使得value < *i
都不为真,第二版本采用comp
进行比较,使得[first, i)
中每个迭代器都有comp(value, *j)
不为真。
复杂度:至多log(last-first)+1
次比较
例子:
int main() {
vector<int> vec = {0, 1, 2, 3, 4, 6, 6, 7, 8};
auto it1 = upper_bound(vec.begin(), vec.end(), 4);
auto it2 = upper_bound(vec.begin(), vec.end(), 5);
for(; it1 != vec.end(); ++it1)
cout << *it1 << " ";
cout << endl;
for(; it2 != vec.end(); ++it2)
cout << *it2 << " ";
return 0;
}
输出:
6 6 7 8
6 6 7 8
equal_range
用法:equal_range(first, last, value)
或equal_range(first, last, value, comp)
定义头文件:<algorithm>
函数原型:
template <class ForwardIterator, class T>
pair<ForwardIterator, ForwardIterator>
equal_range(ForwardIterator first, ForwardIterator last, const T& value);
template <class ForwardIterator, class T, class StrictWeakOrdering>
pair<ForwardIterator, ForwardIterator>
equal_range(ForwardIterator first, ForwardIterator last,
const T& value, StrictWeakOrdering comp);
该函数也是二分查找的一个版本,他会从[first, last)
寻找与value
等价的元素,该函数的返回值本质上是结合了lower_bound
和upper_bound
的返回值,其返回值是一对迭代器i
和j
,其中i
是在不破坏顺序的前提下value
能安插的第一个位置,j
是不破坏顺序的前提下value
可安插的最后一个位置。可以看得出来,区间[i, j)
内的每个元素都等价于value
第一个版本使用operator<
进行比较,使得[first, i)
中每个元素都满足*k < value
,使得[first, j)
中每个元素都满足value < *k
不为真,而能推理出对于区间[i, j)
内每个元素都有value < *k
和*k < value
都不为真。第二个版本同版本一,只不过比较方法改为comp
。
复杂度:至多2log(last-first)+1
次比较
例子:
int main() {
vector<int> vec = {0, 1, 2, 3, 4, 6, 7, 8};
auto it1 = equal_range(vec.begin(), vec.end(), 4);
auto it2 = equal_range(vec.begin(), vec.end(), 5);
cout << *it1.first << " " << *it1.second << endl;
cout << *it2.first << " " << *it2.second << endl;
return 0;
}
输出:
4 6
6 6
合并两个区间
merge
用法:merge(first1, last1, first2, last2, result)
或merge(first1, last1, first2, last2, result, comp)
定义头文件:<algorithm>
函数原型:
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class StrictWeakOrdering>
OutputIterator merge(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, StrictWeakOrdering comp);
该函数能将两个已排序的区间合并成一个以递增顺序的排序区间,会将合并后的区间复制到result
中,该函数属于稳定动作,即能保持原区间的元素的相对位置,对于两个区间中等价的元素,会将第一个区间的元素排在第二个区间的元素前。返回值为result+(last1-first1)+(last2-first2)
第一个版本使用operator<
进行比较合并,第二个版本使用comp
比较合并
复杂度:至多执行(last1-first1)+(last2-first2)-1
次比较。
例子:
int main() {
vector<int> vec1 = {1, 3, 5, 7, 9};
vector<int> vec2 = {0, 2, 4, 6, 8};
vector<int> vec3(10);
auto la = merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
for(auto it = vec3.begin(); it != la; ++it)
cout << *it << " ";
return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9
inplace_merge
用法:inplace_merge(first, middle, last)
或inplace_merge(first, middle, last, comp)
定义头文件:<algorithm>
函数原型:
template <class BidirectionalIterator>
inline void inplace_merge(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last);
template <class BidirectionalIterator, class StrictWeakOrdering>
inline void inplace_merge(BidirectionalIterator first,
BidirectionalIterator middle,
BidirectionalIterator last,
StrictWeakOrdering comp);
如果两个连接在一起的区间[first, middle)
和[middle, last)
都已排序,那么可以用inplace_merge
将两个已排序区间合并成单一已序区间,也就是说如果原区间有两段递增区间构成,那么重新排列后回事这个区间以递增排序。
和merge
一样,该函数也是稳定的,其相对位置不会改变,如果有两个区间中有等价元素,第一个区间的元素会被排在第二个元素之前。
第一个版本使用operator<
进行比较合并,第二个版本使用comp
比较合并
复杂度:最坏n logn
次比较,最好n-1
次比较,n
为last-first
例子:
int main() {
vector<int> vec = {1, 3, 5, 7, 9, 0, 2, 4, 6, 8};
inplace_merge(vec.begin(), vec.begin() + 5, vec.end());
for(auto x : vec)
cout << x << " ";
return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9