STL常见算法运用(上)

特此声明:该博客仅为学习使用,为自己和他人创建一个查询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_offind非常类似,它会在[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);

searchfind有所不同,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)的元素个数,countcount_if之间的关系跟findfind_if差不多,count_if比之count更加一般化

count_ifcount一样有两个版本,只是接口不同而已。同样的,接口二定义于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_backwardcopy一样,可以将[first, last)中的元素拷贝到result中,但是是复制到区间[result-(last-first), result)上,即copy是由前向后复制,copy_backward由后向前复制,会执行赋值操作*(result-1) = *(first-1)等等,返回值为result-(last-first)

copy_backwardcopy一样,只能用来改变[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);

算法swapminmax一样,是少数作用于以引用传入的单一元素上的算法之一,它可以将ab的值互换。

为此可以实现完全的一般化,但是对于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类似,是少数作用于以引用传入的单一元素上的算法之一,它可以将ab的值互换。等价于swap(*a, *b)

现如今已经几乎不再需要该版本的swapC++标准库之所以还保留该函数,只是为了向下兼容

复杂度:常数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)

版本二会对每一个区间的迭代器i1i2执行pred(*i1, *i2),并将运算结果赋值给*result,返回值为result+(last1-first1)

特别的,transform可以被用来原地更改序列,它允许firstresult是同一个迭代器

复杂度:线性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_valuenew_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函数不可能摧毁任何迭代器或者改变firstlast的距离。例如有一个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函数一样不会摧毁任何迭代器或者改变firstlast的距离,也不会改变容器的大小。返回情况也与remove相同。

唯一不同的便是remove是移除值等于value的元素,而remove_if是移除条件符合pred的元素。更具一般性。

复杂度:线性O(n),执行last-firstpred动作

例子

// 移除能被三整除的元素
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函数一样不会摧毁任何迭代器或者改变firstlast的距离,也不会改变容器的大小。返回情况也与remove_copy相同。

唯一不同的便是remove_copy是移除值等于value的元素,而remove_copy_if是移除条件符合pred的元素。更具一般性。

复杂度:线性O(n),执行last-firstpred动作,最多执行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便会移除该群的第一个以外的所有元素。如果想以这个函数移除所有重复元素,必须使所有重复函数相邻,得靠uniquesort搭配使用。

该函数会返回一个迭代器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的区别跟removeremove_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),调用predlast-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),调用predlast-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)……,此时应该注意,resultfirst可以相等,即可以原地计算该区间的部分总和。该函数返回输出迭代器的尾端,即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),其中nlast-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),其中nlast-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),其中nlast-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 < valuevalue < *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_boundupper_bound的返回值,其返回值是一对迭代器ij,其中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次比较,nlast-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
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值