一 概述
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:: 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:: 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:: 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 起)
if ( 1 ) {
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 起)
if ( 1 ) {
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::is_permutation(C++11) (测试不定序的相等性) 请参考此前文章 C++ 算法 区间的比较.
八 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 起)
if ( 1 ) {
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::is_permutation(C++11) (测试不定序的相等性) 请参考此前文章 C++ 算法 区间的比较.
九 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:: 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 中移除)
if ( 1 ) {
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:: 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:: 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:: 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
十五 参考