SiriBlog

siriyang的个人博客


  • 首页

  • 排行榜

  • 标签115

  • 分类37

  • 归档319

  • 关于

  • 搜索

C/CPP参考文档:C++ Algorithm

发表于 2020-01-26 更新于 2021-10-29 分类于 计算机 , 技术 , C/C++ 阅读次数: Valine:
本文字数: 21k 阅读时长 ≈ 19 分钟

C/C++参考文档

修改序列的操作

  定义于头文件 <algorithm>

transform

定义

1
2
3
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,
UnaryOperation unary_op );

功能
  std::transform 应用给定的函数到范围并存储结果于始于 d_first 的另一范围。

  应用一元函数 unary_op 到 [first1, last1) 所定义的范围。

参数

  • first1, last1 - 要变换的第一元素范围
  • d_first - 目标范围的起始,可以等于 first1 或 first2
  • unary_op - 将要应用的一元算符函数。

  函数签名应等价于如下者:

1
Ret fun(const Type &a);

  签名不必有 const & 。
  类型 Type 必须使得 InputIt 类型对象能在解引用后隐式转换到 Type 。 类型 Ret 必须使得 OutputIt 类型对象能被解引用并能被赋 Ret 类型值。 ​

返回值
  指向最后一个变换的元素的输出迭代器。

复杂度
  准确应用 std::distance(first1, last1) 次 unary_op 。

示例

  记得::tolower前面有::, 而且是::tolower,不是::tolower()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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

定义

1
2
template< class T >
void swap( T& a, T& b );

功能
  交换给定值
  1)交换 a 与 b 。
  2)交换 a 与 b 数组。等效于调用 std::swap_ranges(a, a+N, b) 。

参数

  • a, b - 要交换的值

复杂度
  1) 常量
  2) 与 N 成线性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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';
}

输出

1
2
5 3
3 5


swap_ranges

1
2
3
template< class ForwardIt1, class ForwardIt2 >
ForwardIt2 swap_ranges( ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2 );

功能在范围 [first1, last1) 和始于 first2 的另一范围间交换元素。

参数

  • first1, last1 - 要交换的第一个元素范围
  • first2 - 要交换的第二个元素范围的起始

返回值
  指向始于 first2 的范围中被交换的最末元素后一元素的迭代器。

可能的实现

1
2
3
4
5
6
7
8
9
10
template<class ForwardIt1, class ForwardIt2>
ForwardIt2 swap_ranges(ForwardIt1 first1,
ForwardIt1 last1,
ForwardIt2 first2)
{
while (first1 != last1) {
std::iter_swap(first1++, first2++);
}
return first2;
}

复杂度
  与 first1 和 last1 的距离成线性

示例
  演示来自不同容器的子范围交换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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';
}

输出

1
2
-1 -2 -3 4 5
1 2 3 -4 -5

iter_swap

定义

1
2
template< class ForwardIt1, class ForwardIt2 >
void iter_swap( ForwardIt1 a, ForwardIt2 b );

参数

  • a, b - 指向要交换的元素的迭代器

复杂度
  常数

可能的实现

1
2
3
4
5
6
template<class ForwardIt1, class ForwardIt2>
constexpr void iter_swap(ForwardIt1 a, ForwardIt2 b) // C++20 起为 constexpr
{
using std::swap;
swap(*a, *b);
}

示例
  下面是选择排序在 C++ 中的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#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';
}

输出

1
2
Before sort: -7 6 2 4 -1 6 -9 -1 2 -5 10 -9 -5 -3 -5 -3 6 6 1 8
After sort: -9 -9 -7 -5 -5 -5 -3 -3 -1 -1 1 2 2 4 6 6 6 6 8 10

reverse

定义

1
2
template< class BidirIt >
void reverse( BidirIt first, BidirIt last );

功能
  反转 [first, last) 范围中的元素顺序

参数

  • first, last - 要反转的元素的范围

可能的实现

1
2
3
4
5
6
7
template<class BidirIt>
void reverse(BidirIt first, BidirIt last)
{
while ((first != last) && (first != --last)) {
std::iter_swap(first++, last);
}
}

复杂度
  和 first 与 last 间的距离成线性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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;
}

输出

1
2
321
7654

reverse_copy

定义

1
2
template< class BidirIt, class OutputIt >
OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );

功能
  复制来自范围 [first, last) 的元素到始于 d_first 的新范围,使得新范围中元素以逆序排列。

参数

  • first, last - 要复制的元素范围
  • d_first - 新范围的起始

返回值
  指向最后被复制元素后一元素的迭代器。

可能的实现

1
2
3
4
5
6
7
8
template<class BidirIt, class OutputIt>
OutputIt reverse_copy(BidirIt first, BidirIt last, OutputIt d_first)
{
while (first != last) {
*(d_first++) = *(--last);
}
return d_first;
}

复杂度
  与 first 和 last 间的距离成线性。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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';
}

输出

1
2
1 2 3 
3 2 1

排序操作

  定义于头文件 <algorithm>

sort

定义

1
2
3
4
5
template< class RandomIt >
void sort( RandomIt first, RandomIt last );

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

功能
  以升序排序范围 [first, last) 中的元素。不保证维持相等元素的顺序。

  • 1) 用 operator< 比较元素。
  • 2) 用给定的二元比较函数 comp 比较元素。

参数

  • first, last - 要排序的元素范围
  • policy - 所用的执行策略。细节见执行策略。
  • comp - 比较函数对象(即满足比较 (Compare) 概念的对象),若第一参数小于(即先序于)第二参数则返回 ​true 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 RandomIt 类型的对象能在解引用后隐式转换到这两个类型。

复杂度

  • 平均 O(N·log(N)) 次比较,其中 N = std::distance(first, last) 。(C++11 前)
  • O(N·log(N)) 次比较,其中 N = std::distance(first, last) 。(C++11 起)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#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';
}

输出

1
2
3
4
0 1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0

最小/最大操作

  定义于头文件 <algorithm>

max

定义

1
2
3
4
5
6
7
8
9
10
11
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 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 T 类型的对象能隐式转换到这两个类型。

返回值

  • 1-2) a 与 b 的较大者。若它们等价,则返回 a 。
  • 3-4) ilist 中的最大值。若有数个等价于最大者的值,则返回最左侧的这种值。

复杂度

  • 1-2) 准确一次比较
  • 3-4) 准确 ilist.size() - 1 次比较

可能的实现
版本一

1
2
3
4
5
template<class T> 
const T& max(const T& a, const T& b)
{
return (a < b) ? b : a;
}

版本二

1
2
3
4
5
template<class T, class Compare> 
const T& max(const T& a, const T& b, Compare comp)
{
return (comp(a, b)) ? b : a;
}

版本三

1
2
3
4
5
template< class T >
T max( std::initializer_list<T> ilist)
{
return *std::max_element(ilist.begin(), ilist.end());
}

版本四

1
2
3
4
5
template< class T, class Compare >
T max( std::initializer_list<T> ilist, Compare comp )
{
return *std::max_element(ilist.begin(), ilist.end(), comp);
}

注意
  若参数之一是右值,且返回该参数,则以引用捕获 std::max 的结果会产生一个悬垂引用:

1
2
3
int n = 1;
const int& r = std::max(n-1, n+1);
// r 为悬垂

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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';
}

输出

1
2
3
larger of 1 and 9999: 9999
larger of 'a', and 'b': b
longest of "foo", "bar", and "hello": hello

max_element

定义

1
2
3
4
5
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 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 ForwardIt 类型的对象能在解引用后隐式转换到这两个类型。 ​

返回值
  指向范围 [first, last) 中最大元素的迭代器。若范围中有多个元素等价于最大元素,则返回指向首个这种元素的迭代器。若范围为空则返回 last 。

复杂度
  准确比较 max(N-1,0) 次,其中 N = std::distance(first, last) 。

可能的实现
版本一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class ForwardIt>
ForwardIt max_element(ForwardIt first, ForwardIt last)
{
if (first == last) {
return last;
}
ForwardIt largest = first;
++first;
for (; first != last; ++first) {
if (*largest < *first) {
largest = first;
}
}
return largest;
}

版本二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class ForwardIt, class Compare>
ForwardIt max_element(ForwardIt first, ForwardIt last,
Compare comp)
{
if (first == last) {
return last;
}
ForwardIt largest = first;
++first;
for (; first != last; ++first) {
if (comp(*largest, *first)) {
largest = first;
}
}
return largest;
}

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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);
}

输出:

1
2
max element at: 5
max element (absolute) at: 2

min

定义

1
2
3
4
5
6
7
8
9
10
11
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 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 T 类型的对象能隐式转换到这两个类型。 ​

返回值

  • 1-2) a 与 b 的较小者。若值等价,则返回 a 。
  • 3-4) ilist 中的最小值。若有数个等价于最小者的值,则返回最左侧的这种值。

复杂度

  • 1-2) 准确一次比较
  • 3-4) 准确 ilist.size() - 1 次比较

可能的实现
版本一

1
2
3
4
5
template<class T> 
const T& min(const T& a, const T& b)
{
return (b < a) ? b : a;
}

版本二

1
2
3
4
5
template<class T, class Compare> 
const T& min(const T& a, const T& b, Compare comp)
{
return (comp(b, a)) ? b : a;
}

版本三

1
2
3
4
5
template<class T>
T min( std::initializer_list<T> ilist)
{
return *std::min_element(ilist.begin(), ilist.end());
}

版本四

1
2
3
4
5
template<class T, class Compare>
T min(std::initializer_list<T> ilist, Compare comp)
{
return *std::min_element(ilist.begin(), ilist.end(), comp);
}

警告
  若参数之一是右值,且返回该参数,则以引用捕获 std::min 的结果会产生一个悬垂引用:

1
2
3
int n = 1;
const int& r = std::min(n-1, n+1);
// r 为悬垂

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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';
}

输出

1
2
3
smaller of 1 and 9999: 1
smaller of 'a', and 'b': a
shortest of "foo", "bar", and "hello": foo

min_element

定义

1
2
3
4
5
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 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 ForwardIt 类型的对象能在解引用后隐式转换到这两个类型。 ​

返回值
  指向范围 [first, last) 中最小元素的迭代器。若范围中有多个元素等价于最小元素,则返回指向首个这种元素的迭代器。若范围为空则返回 last 。

复杂度
  准确比较 max(N-1,0) 次,其中 N = std::distance(first, last) 。

可能的实现
版本一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class ForwardIt>
ForwardIt min_element(ForwardIt first, ForwardIt last)
{
if (first == last) return last;

ForwardIt smallest = first;
++first;
for (; first != last; ++first) {
if (*first < *smallest) {
smallest = first;
}
}
return smallest;
}

版本二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class ForwardIt, class Compare>
ForwardIt min_element(ForwardIt first, ForwardIt last, Compare comp)
{
if (first == last) return last;

ForwardIt smallest = first;
++first;
for (; first != last; ++first) {
if (comp(*first, *smallest)) {
smallest = first;
}
}
return smallest;
}

示例

1
2
3
4
5
6
7
8
9
10
11
#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);
}

输出:

1
min element at: 1

排列操作

  定义于头文件 <algorithm>

next_permutation

定义

1
2
3
4
5
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 。

  比较函数的签名应等价于如下:

1
bool cmp(const Type1 &a, const Type2 &b);

  虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1 与 Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
  类型 Type1 与 Type2 必须使得 BidirIt 类型的对象能在解引用后隐式转换到这两个类型。 ​

返回值
  若新排列按字典序大于旧者则为 true 。若抵达最后重排并重置范围为首个排列则为 false 。

复杂度
  至多 N/2 次交换,其中 N = std::distance(first, last) 。

  典型实现在排列的整个序列上,平均每次调用使用约 3 次比较和 1.5 次交换。

可能的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<class BidirIt>
bool next_permutation(BidirIt first, BidirIt last)
{
if (first == last) return false;
BidirIt i = last;
if (first == --i) return false;

while (true) {
BidirIt i1, i2;

i1 = i;
if (*--i < *i1) {
i2 = last;
while (!(*i < *--i2))
;
std::iter_swap(i, i2);
std::reverse(i1, last);
return true;
}
if (i == first) {
std::reverse(first, last);
return false;
}
}
}

示例
  下列代码打印字符串 “aba“ 的全部三种排列

1
2
3
4
5
6
7
8
9
10
11
12
#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()));
}

输出

1
2
3
aab
aba
baa

prev_permutation

定义

1
2
3
4
5
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 。

复杂度
  至多 (last-first)/2 次交换。

  典型实现在排列的整个序列上,平均每次调用使用约 3 次比较和 1.5 次交换。

可能的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template<class BidirIt>
bool prev_permutation(BidirIt first, BidirIt last)
{
if (first == last) return false;
BidirIt i = last;
if (first == --i) return false;

while (1) {
BidirIt i1, i2;

i1 = i;
if (*i1 < *--i) {
i2 = last;
while (!(*--i2 < *i))
;
std::iter_swap(i, i2);
std::reverse(i1, last);
return true;
}
if (i == first) {
std::reverse(first, last);
return false;
}
}
}

示例
下列代码以逆序打印字符串 “abc“ 的所有六个排列

1
2
3
4
5
6
7
8
9
10
11
12
13
#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';
}

输出

1
cba cab bca bac acb abc

参考资料
  • cppreference.com 算法库
-------- 本文结束 感谢阅读 --------
相关文章
  • C/CPP参考文档:C I/O
  • C/C++参考文档:C Time & Date
  • C/C++参考文档:C Memory
  • C/C++参考文档:C String & Character
  • C/CPP参考文档:C Math
觉得文章写的不错的话,请我喝瓶怡宝吧!😀
SiriYang 微信支付

微信支付

SiriYang 支付宝

支付宝

  • 本文标题: C/CPP参考文档:C++ Algorithm
  • 本文作者: SiriYang
  • 创建时间: 2020年01月26日 - 11时01分
  • 修改时间: 2021年10月29日 - 18时10分
  • 本文链接: https://blog.siriyang.cn/posts/20200126115533id.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
C/C++ 文档
Dev-C++ 开启对C++ 11的支持
C/CPP参考文档:C Math
  • 文章目录
  • 站点概览
SiriYang

SiriYang

努力搬砖攒钱买镜头的摄影迷
319 日志
33 分类
88 标签
RSS
GitHub E-Mail
Creative Commons
Links
  • 友情链接
  • 作品商铺

  1. 修改序列的操作
    1. transform
    2. swap
    3. swap_ranges
    4. iter_swap
    5. reverse
    6. reverse_copy
  2. 排序操作
    1. sort
  3. 最小/最大操作
    1. max
    2. max_element
    3. min
    4. min_element
  4. 排列操作
    1. next_permutation
    2. prev_permutation
蜀ICP备19008337号 © 2019 – 2025 SiriYang | 1.7m | 25:41
0%