C++ algorithm基操
序列修改
transform
功能:大小写转换
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,UnaryOperation unary_op );
参数:
first1
,last1
- 要变换的第一元素范围d_first
- 目标范围的起始,可以等于first1
或first2
unary_op
- 将要应用的一元算符函数。
PS:记得::tolower
前面有::
, 而且是::tolower
,不是::tolower()
#include <iostream>
#include <algorithm>
using namespace std;
string s;
int main() {
cout<<"请输入一个含大写的字符串:";
string str;
cin>>str;
///转小写
transform(str.begin(),str.end(),str.begin(),::tolower);
cout<<"转化为小写后为:"<<str<<endl;
transform(str.begin(),str.end(),str.begin(),::toupper);
cout<<"转化为大写后为:"<<str<<endl;
return 0;
}
swap
功能:交换值
void swap( T& a, T& b );
参数:
a
,b
- 要交换的值
#include <algorithm>
#include <iostream>
int main()
{
int a = 5, b = 3;
// 前
std::cout << a << ' ' << b << '\n';
std::swap(a,b);
// 后
std::cout << a << ' ' << b << '\n';
}
swap_ranges
功能:在范围 [first1, last1)
和始于 first2
的另一范围间交换元素。
参数
first1
,last1
- 要交换的第一个元素范围first2
- 要交换的第二个元素范围的起始
返回值
指向始于 first2
的范围中被交换的最末元素后一元素的迭代器。
示例
演示来自不同容器的子范围交换
#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
std::list<int> l = {-1, -2, -3, -4, -5};
std::swap_ranges(v.begin(), v.begin()+3, l.begin());
for(int n : v)
std::cout << n << ' ';
std::cout << '\n';
for(int n : l)
std::cout << n << ' ';
std::cout << '\n';
}
iter_swap
定义
template< class ForwardIt1, class ForwardIt2 >
void iter_swap( ForwardIt1 a, ForwardIt2 b );
参数
a
,b
- 指向要交换的元素的迭代器
示例
下面是选择排序在 C++ 中的实现
#include <random>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
template<class ForwardIt>
void selection_sort(ForwardIt begin, ForwardIt end)
{
for (ForwardIt i = begin; i != end; ++i)
std::iter_swap(i, std::min_element(i, end));
}
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(-10, 10);
std::vector<int> v;
std::generate_n(back_inserter(v), 20, bind(dist, gen));
std::cout << "Before sort: ";
for(auto e : v) std::cout << e << " ";
selection_sort(v.begin(), v.end());
std::cout << "\nAfter sort: ";
for(auto e : v) std::cout << e << " ";
std::cout << '\n';
}
reverse
定义
template< class BidirIt >
void reverse( BidirIt first, BidirIt last );
功能
反转 [first, last)
范围中的元素顺序
参数
first
,last
- 要反转的元素的范围
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> v{1,2,3};
std::reverse(std::begin(v), std::end(v));
for(auto e : v) std::cout << e;
std::cout << '\n';
int a[] = {4, 5, 6, 7};
std::reverse(std::begin(a), std::end(a));
for(auto e : a) std::cout << e;
}
reverse_copy
定义
template< class BidirIt, class OutputIt >
OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );
功能
复制来自范围 [first, last)
的元素到始于 d_first
的新范围,使得新范围中元素以逆序排列。
参数
first
,last
- 要复制的元素范围d_first
- 新范围的起始
返回值
指向最后被复制元素后一元素的迭代器。
示例
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::vector<int> v({1,2,3});
for (const auto& value : v) {
std::cout << value << " ";
}
std::cout << '\n';
std::vector<int> destination(3);
std::reverse_copy(std::begin(v), std::end(v), std::begin(destination));
for (const auto& value : destination) {
std::cout << value << " ";
}
std::cout << '\n';
}
排序操作
定义于头文件 <algorithm>
sort
定义
template< class RandomIt >
void sort( RandomIt first, RandomIt last );
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
功能
以升序排序范围 [first, last) 中的元素。不保证维持相等元素的顺序。
-
- 用 operator< 比较元素。
-
- 用给定的二元比较函数 comp 比较元素。
参数
first
,last
- 要排序的元素范围policy
- 所用的执行策略。细节见执行策略。comp
- 比较函数对象(即满足比较 (Compare) 概念的对象),若第一参数小于(即先序于)第二参数则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
示例
#include <algorithm>
#include <functional>
#include <array>
#include <iostream>
int main()
{
std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
// 用默认的 operator< 排序
std::sort(s.begin(), s.end());
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用标准库比较函数对象排序
std::sort(s.begin(), s.end(), std::greater<int>());
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用自定义函数对象排序
struct {
bool operator()(int a, int b) const
{
return a < b;
}
} customLess;
std::sort(s.begin(), s.end(), customLess);
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// 用 lambda 表达式排序
std::sort(s.begin(), s.end(), [](int a, int b) {
return b < a;
});
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
}
最小/最大操作
max
定义
template< class T >
const T& max( const T& a, const T& b );
template< class T, class Compare >
const T& max( const T& a, const T& b, Compare comp );
template< class T >
T max( std::initializer_list<T> ilist );
template< class T, class Compare >
T max( std::initializer_list<T> ilist, Compare comp );
功能
返回给定值中的较大者。
- 1-2) 返回
a
与b
的较大者。 - 3-4) 返回
initializer_list ilist
中值的最大者。 - (1,3) 版本用
operator<
比较元素, (2,4) 版本用给定的比较函数comp
。
参数
a
,b
- 要比较的值ilist
- 拥有要比较的值的initializer_list
cmp
- 比较函数对象(即满足比较 (Compare) 要求的对象),若若a
小于b
,则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
- 1-2)
a
与b
的较大者。若它们等价,则返回a
。 - 3-4)
ilist
中的最大值。若有数个等价于最大者的值,则返回最左侧的这种值。
示例
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::cout << "larger of 1 and 9999: " << std::max(1, 9999) << '\n'
<< "larger of 'a', and 'b': " << std::max('a', 'b') << '\n'
<< "longest of \"foo\", \"bar\", and \"hello\": " <<
std::max( { "foo", "bar", "hello" },
[](const std::string& s1, const std::string& s2) {
return s1.size() < s2.size();
}) << '\n';
}
max_element
定义
template< class ForwardIt >
ForwardIt max_element(ForwardIt first, ForwardIt last );
template< class ForwardIt, class Compare >
ForwardIt max_element(ForwardIt first, ForwardIt last, Compare comp );
功能
寻找范围 [first, last)
中的最大元素。
1) 用 operator<
比较元素。
2) 用给定的二元比较函数 comp
比较元素。
参数
first
,last
- 定义要检验范围的向前迭代器comp
- 比较函数对象(即满足比较 (Compare) 要求的对象),若首个参数小于第二个,则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
示例
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
static bool abs_compare(int a, int b)
{
return (std::abs(a) < std::abs(b));
}
int main()
{
std::vector<int> v{ 3, 1, -14, 1, 5, 9 };
std::vector<int>::iterator result;
result = std::max_element(v.begin(), v.end());
std::cout << "max element at: " << std::distance(v.begin(), result) << '\n';
result = std::max_element(v.begin(), v.end(), abs_compare);
std::cout << "max element (absolute) at: " << std::distance(v.begin(), result);
}
min
定义
template< class T >
const T& min( const T& a, const T& b );
template< class T, class Compare >
const T& min( const T& a, const T& b, Compare comp );
template< class T >
T min( std::initializer_list<T> ilist );
template< class T, class Compare >
T min( std::initializer_list<T> ilist, Compare comp );
功能
返回给定值中的较小者。
- 1-2) 返回
a
与b
的较小者。 - 3-4) 返回
initializer_list ilist
中值的最小者。 - (1,3) 版本用
operator<
比较元素, (2,4) 版本用给定的比较函数comp
。
参数
a
,b
- 要比较的值ilist
- 拥有要比较的值的initializer_list
cmp
- 比较函数对象(即满足比较 (Compare) 要求的对象),若a
小于b
,则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
- 1-2)
a
与b
的较小者。若值等价,则返回a
。 - 3-4)
ilist
中的最小值。若有数个等价于最小者的值,则返回最左侧的这种值。
警告
若参数之一是右值,且返回该参数,则以引用捕获 std::min
的结果会产生一个悬垂引用:
int n = 1;
const int& r = std::min(n-1, n+1);
// r 为悬垂
示例
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::cout << "smaller of 1 and 9999: " << std::min(1, 9999) << '\n'
<< "smaller of 'a', and 'b': " << std::min('a', 'b') << '\n'
<< "shortest of \"foo\", \"bar\", and \"hello\": " <<
std::min( { "foo", "bar", "hello" },
[](const std::string& s1, const std::string& s2) {
return s1.size() < s2.size();
}) << '\n';
}
输出
smaller of 1 and 9999: 1
smaller of 'a', and 'b': a
shortest of "foo", "bar", and "hello": foo
min_element
定义
template< class ForwardIt >
ForwardIt min_element( ForwardIt first, ForwardIt last );
template< class ForwardIt, class Compare >
ForwardIt min_element( ForwardIt first, ForwardIt last, Compare comp );
功能
寻找范围 [first, last)
中的最小元素。
1) 用 operator<
比较元素。
2) 用给定的二元比较函数 comp
比较元素。
参数
first
,last
- 定义要检验范围的向前迭代器comp
- 比较函数对象(即满足比较 (Compare) 要求的对象),若a
小于b
,则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
指向范围 [first, last)
中最小元素的迭代器。若范围中有多个元素等价于最小元素,则返回指向首个这种元素的迭代器。若范围为空则返回 last
。
示例
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{3, 1, 4, 1, 5, 9};
std::vector<int>::iterator result = std::min_element(std::begin(v), std::end(v));
std::cout << "min element at: " << std::distance(std::begin(v), result);
}
排列操作
定义于头文件 <algorithm>
next_permutation
定义
template< class BidirIt >
bool next_permutation( BidirIt first, BidirIt last );
template< class BidirIt, class Compare >
bool next_permutation( BidirIt first, BidirIt last, Compare comp );
功能
变换范围 [first, last)
为来自所有按相对于 operator<
或 comp
的字典序的下个排列。若这种排列存在则返回 true
,否则变换范围为首个排列(如同用 std::sort(first, last)
)并返回 false
。
参数
first
,last
- 要重排的元素范围comp
- 比较函数对象(即满足比较 (Compare) 要求的对象),若首个参数小于第二个,则返回true
。
比较函数的签名应等价于如下:
bool cmp(const Type1 &a, const Type2 &b);
返回值
若新排列按字典序大于旧者则为 true
。若抵达最后重排并重置范围为首个排列则为 false
。
示例
下列代码打印字符串 “aba
“ 的全部三种排列
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "aba";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
prev_permutation
定义
template< class BidirIt >
bool prev_permutation( BidirIt first, BidirIt last);
template< class BidirIt, class Compare >
bool prev_permutation( BidirIt first, BidirIt last, Compare comp);
功能
变换范围 [first, last)
为来自于相对于 operator<
或 comp
的字典序的所有排列集合的上个排列。若这种排列存在则返回 true
,否则变换范围为末排列(如同用 std::sort(first, last); std::reverse(first, last);
)并返回 false
。
返回值
若新排列按字典序前趋旧排列则为 true
。若抵达首个排列并重置范围为最末排列则为 false
。
示例
下列代码以逆序打印字符串 “abc
“ 的所有六个排列
#include <algorithm>
#include <string>
#include <iostream>
#include <functional>
int main()
{
std::string s="abc";
std::sort(s.begin(), s.end(), std::greater<char>());
do {
std::cout << s << ' ';
} while(std::prev_permutation(s.begin(), s.end()));
std::cout << '\n';
}