C++ 标准库 变序型算法

一 概述

  • C++ 标准库中提供了很多算法,定义于头文件 < algorithm >。本文主要探究以下用于 区间元素变序 的算法:
    • std::reverse 逆转范围中的元素顺序
    • std::reverse_copy 创建一个范围的逆向副本
    • std::rotate 旋转范围中的元素顺序
    • std::rotate_copy 复制并旋转元素范围
    • std::next_permutation 产生某个元素范围的按字典顺序的下一个较大的排列
    • std::prev_permutation 产生某个元素范围的按字典顺序的下一个较小的排列
    • std::shuffle(C++11) 随机重排范围中的元素
    • std::random_shuffle(C++14弃用C++17移除) 随机重排范围中的元素
    • std::partition 将范围中的元素分为两组
    • std::stable_partition 将元素分为两组,同时保留其相对顺序
    • std::partition_copy 复制并将范围中的元素分为两组

二 辅助函数

三 std::reverse

  • 定义
template< class BidirIt >
void reverse( BidirIt first, BidirIt last );(1)(C++20)
template< class BidirIt >
constexpr void reverse( BidirIt first, BidirIt last );(1)(C++20)
template< class ExecutionPolicy, class BidirIt >
void reverse( ExecutionPolicy&& policy, BidirIt first,
              BidirIt last );(2)(C++17)
if (1) {
  // std::reverse 逆转范围中的元素顺序
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before reverse vc: ", vc);
  std::reverse(vc.begin(), vc.end());
  print(" after reverse vc: ", vc);
}
  • 结果
before reverse vc: 1 2 3 4 5 6 7 8 9
 after reverse vc: 9 8 7 6 5 4 3 2 1

四 std::reverse_copy

  • 定义
template< class BidirIt, class OutputIt >
OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first );(1)(C++20)
template< class BidirIt, class OutputIt >
constexpr OutputIt reverse_copy( BidirIt first, BidirIt last, OutputIt d_first);(1)(C++20)
template< class ExecutionPolicy, class BidirIt, class ForwardIt >
ForwardIt reverse_copy( ExecutionPolicy&& policy, BidirIt first, BidirIt last,
                        ForwardIt d_first );(2)(C++17)
if (1) {
  // std::reverse_copy 创建一个范围的逆向副本
  std::vector<int> vc1;
  fill(vc1, 1, 9);
  std::vector<int> vc2;
  print("before reverse_copy vc1: ", vc1);
   print("before reverse_copy vc2: ", vc2);
  std::reverse_copy(vc1.begin(), vc1.end(), std::back_inserter(vc2));
  print(" after reverse_copy vc1: ", vc1);
  print(" after reverse_copy vc2: ", vc2);
}
  • 结果
before reverse_copy vc1: 1 2 3 4 5 6 7 8 9
before reverse_copy vc2:
 after reverse_copy vc1: 1 2 3 4 5 6 7 8 9
 after reverse_copy vc2: 9 8 7 6 5 4 3 2 1

五 std::rotate

  • 定义
template< class ForwardIt >
void      rotate( ForwardIt first, ForwardIt n_first, ForwardIt last );(1)(C++11)
template< class ForwardIt >
ForwardIt rotate( ForwardIt first, ForwardIt n_first, 
                  ForwardIt last );(1)(C++11)(C++20)
template< class ForwardIt >
constexpr ForwardIt
          rotate( ForwardIt first, ForwardIt n_first, ForwardIt last );(1)(C++20)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt rotate( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt n_first, ForwardIt last );(2)(C++17)
  • 说明
    • std::rotate 交换范围 [first, last) 中的元素,操作后满足元素 n_first 成为新范围的首个元素,而 n_first - 1 成为最后元素。
    • 前提条件是 [first, n_first) 和 [n_first, last) 为合法范围。
  • Demo
if (1) {
  // std::rotate 旋转范围中的元素顺序
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before rotate vc: ", vc);
  std::rotate(vc.begin(), vc.begin() + 3, vc.end());
  print(" after rotate vc: ", vc);
}
  • 结果
before rotate vc: 1 2 3 4 5 6 7 8 9
 after rotate vc: 4 5 6 7 8 9 1 2 3

六 std::rotate_copy

  • 定义
template< class ForwardIt, class OutputIt >
OutputIt rotate_copy( ForwardIt first, ForwardIt n_first,
                      ForwardIt last, OutputIt d_first );(1)(C++20)
template< class ForwardIt, class OutputIt >
constexpr OutputIt rotate_copy( ForwardIt first, ForwardIt n_first,
                                ForwardIt last, OutputIt d_first );(1)(C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 rotate_copy( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 n_first,
                        ForwardIt1 last, ForwardIt2 d_first );(2)(C++17)
  • Demo
if (1) {
  // std::rotate_copy 复制并旋转元素范围
  std::vector<int> vc1;
  fill(vc1, 1, 9);
  std::vector<int> vc2;
  print("before rotate_copy vc1: ", vc1);
  print("before rotate_copy vc2: ", vc2);
  std::rotate_copy(vc1.begin(), vc1.begin() + 3, vc1.end(), std::back_inserter(vc2));
  print(" after rotate_copy vc1: ", vc1);
  print(" after rotate_copy vc2: ", vc2);
}
  • 结果
before rotate_copy vc1: 1 2 3 4 5 6 7 8 9
before rotate_copy vc2:
 after rotate_copy vc1: 1 2 3 4 5 6 7 8 9
 after rotate_copy vc2: 4 5 6 7 8 9 1 2 3

七 std::next_permutation

  • 定义
template< class BidirIt >
bool next_permutation( BidirIt first, BidirIt last );(1)(C++20)
template< class BidirIt >
constexpr bool next_permutation( BidirIt first, BidirIt last );(1)(C++20)
template< class BidirIt, class Compare >
bool next_permutation( BidirIt first, BidirIt last, Compare comp );(2)(C++20)
template< class BidirIt, class Compare >
constexpr bool next_permutation( BidirIt first, BidirIt last, Compare comp );(2)(C++20)
  • Demo
if (1) {
  // std::next_permutation 产生某个元素范围的按字典顺序的下一个较大的排列
  std::vector<int> vc;
  fill(vc, 1, 3);
  print("before next_permutation vc: ", vc);
  while(std::next_permutation(vc.begin(), vc.end())){
    print(" after next_permutation vc: ", vc);
  }
}
  • 结果
before next_permutation vc: 1 2 3
 after next_permutation vc: 1 3 2
 after next_permutation vc: 2 1 3
 after next_permutation vc: 2 3 1
 after next_permutation vc: 3 1 2
 after next_permutation vc: 3 2 1

八 std::prev_permutation

  • 定义
template< class BidirIt >
bool prev_permutation( BidirIt first, BidirIt last);(1)(C++20)
template< class BidirIt >
constexpr bool prev_permutation( BidirIt first, BidirIt last);(1)(C++20)	
template< class BidirIt, class Compare >
bool prev_permutation( BidirIt first, BidirIt last, Compare comp);(2)(C++20)
template< class BidirIt, class Compare >
constexpr bool prev_permutation( BidirIt first, BidirIt last, 
                                 Compare comp);(2)(C++20)
  • Demo
if (1) {
  // std::prev_permutation 产生某个元素范围的按字典顺序的下一个较小的排列
  std::vector<int> vc{3,2,1};
  print("before prev_permutation vc: ", vc);
  while (std::prev_permutation(vc.begin(), vc.end())) {
    print(" after prev_permutation vc: ", vc);
  }
}
  • 结果
before prev_permutation vc: 3 2 1
 after prev_permutation vc: 3 1 2
 after prev_permutation vc: 2 3 1
 after prev_permutation vc: 2 1 3
 after prev_permutation vc: 1 3 2
 after prev_permutation vc: 1 2 3

九 std::shuffle(C++11)

  • 定义
template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );(C++11)
  • g为随机数生成器,标准未钦定实现,所以即使你用准确相同的URBG ,也可能通过不同的标准库实现得到不同结果。
  • Demo
if (1) {
  // std::shuffle(C++11) 随机重排范围中的元素
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before shuffle vc: ", vc);
  std::shuffle(vc.begin(), vc.end(), std::random_device());
  print(" after shuffle vc: ", vc);
}
  • 结果
before shuffle vc: 1 2 3 4 5 6 7 8 9
 after shuffle vc: 5 7 2 3 8 6 4 1 9

十 std::random_shuffle

  • 定义
template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );(1)(C++14中弃用)(C++17中移除)	
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc& r );(2)(C++11)
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last,
                     RandomFunc&& r );(2)(C++11)(C++14 中弃用)(C++17 中移除)
  • Demo
if (1) {
  // std::random_shuffle(C++14弃用C++17移除) 随机重排范围中的元素
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before random_shuffle vc: ", vc);
  std::random_shuffle(vc.begin(), vc.end());
  print(" after random_shuffle vc: ", vc);
}
  • 结果
before random_shuffle vc: 1 2 3 4 5 6 7 8 9
 after random_shuffle vc: 9 2 7 3 1 6 8 4 5

十一 std::partition

  • 定义
template< class BidirIt, class UnaryPredicate >
BidirIt partition( BidirIt first, BidirIt last, UnaryPredicate p );(1)(C++11)
template< class ForwardIt, class UnaryPredicate >
ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );(1)(C++11)(C++20)
template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );(1)(C++20)
template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate >
ForwardIt partition( ExecutionPolicy&& policy,
                     ForwardIt first, ForwardIt last, UnaryPredicate p );(2)(C++17)
if (1) {
  // std::partition 将范围中的元素分为两组
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before partition vc: ", vc);
  std::partition(vc.begin(), vc.end(), even);
  print(" after partition vc: ", vc);
}
  • 结果
before partition vc: 1 2 3 4 5 6 7 8 9
 after partition vc: 8 2 6 4 5 3 7 1 9

十二 std::stable_partition

  • 定义
template< class BidirIt, class UnaryPredicate >
BidirIt stable_partition( BidirIt first, BidirIt last, UnaryPredicate p );(1)	
template< class ExecutionPolicy, class BidirIt, class UnaryPredicate >
BidirIt stable_partition( ExecutionPolicy&& policy, BidirIt first, BidirIt last, 
                          UnaryPredicate p );(2)(C++17)
if (1) {
  // std::stable_partition 将元素分为两组,同时保留其相对顺序
  std::vector<int> vc;
  fill(vc, 1, 9);
  print("before stable_partition vc: ", vc);
  std::stable_partition(vc.begin(), vc.end(), even);
  print(" after stable_partition vc: ", vc);
}
  • 结果
before stable_partition vc: 1 2 3 4 5 6 7 8 9
 after stable_partition vc: 2 4 6 8 1 3 5 7 9

十三 std::partition_copy

  • 定义
template< class InputIt, class OutputIt1,class OutputIt2, class UnaryPredicate >
std::pair<OutputIt1, OutputIt2>
     partition_copy( InputIt first, InputIt last, OutputIt1 d_first_true, 
                     OutputIt2 d_first_false, UnaryPredicate p );(1)(C++11)(C++20)
template< class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate >
constexpr std::pair<OutputIt1, OutputIt2>
               partition_copy( InputIt first, InputIt last, OutputIt1 d_first_true, 
                               OutputIt2 d_first_false, UnaryPredicate p );(1)(C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
          class ForwardIt3, class UnaryPredicate >
std::pair<ForwardIt2, ForwardIt3>
     partition_copy( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
                     ForwardIt2 d_first_true, ForwardIt3 d_first_false,
                     UnaryPredicate p );(2)(C++17)
  • 说明
    • ExecutionPolicy 请参考此前文章 std::find std::execution。
    • 从范围 [first, last) 复制元素到二个不同范围,取决于谓词 p 的返回值。复制满足谓词 p 的元素到始于 d_first_true 的范围。复制剩余元素到始于 d_first_false 的范围。
    • 若输入范围与任一输出范围重叠,则行为未定义。
  • Demo
if (1) {
  // std::partition_copy 复制并将范围中的元素分为两组
  std::vector<int> vc;
  fill(vc, 1, 9);
  std::vector<int> vc_true;
  std::vector<int> vc_false;
  print("before partition_copy vc: ", vc);
  print("before partition_copy vc_true: ", vc_true);
  print("before partition_copy vc_false: ", vc_false);
  std::partition_copy(vc.begin(), vc.end(), std::back_inserter(vc_true), 
                      std::back_inserter(vc_false), even);
  print(" after partition_copy vc: ", vc);
  print(" after partition_copy vc_true: ", vc_true);
  print(" after partition_copy vc_false: ", vc_false);
}
  • 结果
before partition_copy vc: 1 2 3 4 5 6 7 8 9
before partition_copy vc_true:
before partition_copy vc_false:
 after partition_copy vc: 1 2 3 4 5 6 7 8 9
 after partition_copy vc_true: 2 4 6 8
 after partition_copy vc_false: 1 3 5 7 9

十四 github

  • 所有Demo 已上传github cplusplus
  • mutating_algorithm.cpp

十五 参考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章