一 概述
C++ 標準庫中提供了很多算法,定義於頭文件 < algorithm >。本文主要探究以下用於 移除區間元素 的算法:
std::remove 移除滿足特定判別標準的元素
std::remove_if 移除滿足特定判別標準的元素
std::remove_copy 複製一個範圍的元素,忽略滿足特定判別標準的元素。
std::remove_copy_if 複製一個範圍的元素,忽略滿足特定判別標準的元素。
std::unique 移除範圍內的連續重複元素
std::unique_copy 創建某範圍的不含連續重複元素的副本
二 輔助函數
template < typename It1, typename It2>
void print2 ( const std:: string& pre, const It1& beg, const It2& end) {
std:: cout << pre;
std:: copy ( beg, end,
std:: ostream_iterator< int > ( std:: cout, " " ) ) ;
std:: cout << std:: endl;
}
三 std::remove
template < class ForwardIt , class T >
ForwardIt remove ( ForwardIt first, ForwardIt last, const T& value ) ; ( 1 ) ( C++ 20 前)
template < class ForwardIt , class T >
constexpr ForwardIt remove ( ForwardIt first, ForwardIt last, const T& value ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt , class T >
ForwardIt remove ( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
const T& value ) ; ( 2 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc;
fill ( vc, 1 , 9 ) ;
print ( "before remove vc: " , vc) ;
auto it = std:: remove ( vc. begin ( ) , vc. end ( ) , 1 ) ;
print ( "after remove vc: " , vc) ;
print2 ( "after remove vc: " , vc. begin ( ) , it) ;
}
before remove vc: 1 2 3 4 5 6 7 8 9
after remove vc: 2 3 4 5 6 7 8 9 9
after remove vc: 2 3 4 5 6 7 8 9
說明
移除滿足條件元素,後面的元素“移動賦值”。
保持剩餘元素的相對順序,且不更改容器的物理大小。
四 std::remove_if
template < class ForwardIt , class UnaryPredicate >
ForwardIt remove_if ( ForwardIt first, ForwardIt last, UnaryPredicate p ) ; ( 1 ) ( C++ 20 前)
template < class ForwardIt , class UnaryPredicate >
constexpr ForwardIt remove_if ( ForwardIt first, ForwardIt last, UnaryPredicate p ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt , class UnaryPredicate >
ForwardIt remove_if ( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
UnaryPredicate p ) ; ( 2 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc;
fill ( vc, 1 , 9 ) ;
print ( "before remove_if vc: " , vc) ;
auto it = std:: remove_if ( vc. begin ( ) , vc. end ( ) , even) ;
print ( "after remove_if vc: " , vc) ;
print2 ( "after remove_if vc: " , vc. begin ( ) , it) ;
}
before remove_if vc: 1 2 3 4 5 6 7 8 9
after remove_if vc: 1 3 5 7 9 6 7 8 9
after remove_if vc: 1 3 5 7 9
五 std::remove_copy
template < class InputIt , class OutputIt , class T >
OutputIt remove_copy ( InputIt first, InputIt last, OutputIt d_first, const T& value ) ; ( 1 ) ( C++ 20 前)
template < class InputIt , class OutputIt , class T >
constexpr OutputIt remove_copy ( InputIt first, InputIt last, OutputIt d_first,
const T& value ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt1 , class ForwardIt2 , class T >
ForwardIt2 remove_copy ( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, const T& value ) ; ( 2 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc1;
fill ( vc1, 1 , 9 ) ;
std:: vector< int > vc2;
print ( "before remove_copy vc1: " , vc1) ;
print ( "before remove_copy vc2: " , vc2) ;
auto it = std:: remove_copy ( vc1. begin ( ) , vc1. end ( ) , std:: back_inserter ( vc2) , 1 ) ;
print ( "after remove_copy vc1: " , vc1) ;
print ( "after remove_copy vc2: " , vc2) ;
}
before remove_copy vc1: 1 2 3 4 5 6 7 8 9
before remove_copy vc2:
after remove_copy vc1: 1 2 3 4 5 6 7 8 9
after remove_copy vc2: 2 3 4 5 6 7 8 9
六 std::remove_copy_if
template < class InputIt , class OutputIt , class UnaryPredicate >
OutputIt remove_copy_if ( InputIt first, InputIt last, OutputIt d_first,
UnaryPredicate p ) ; ( 1 ) ( C++ 20 前)
template < class InputIt , class OutputIt , class UnaryPredicate >
constexpr OutputIt remove_copy_if ( InputIt first, InputIt last, OutputIt d_first,
UnaryPredicate p ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt1 , class ForwardIt2 , class UnaryPredicate >
ForwardIt2 remove_copy_if ( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, UnaryPredicate p ) ; ( 2 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc1;
fill ( vc1, 1 , 9 ) ;
std:: vector< int > vc2;
print ( "before remove_copy_if vc1: " , vc1) ;
print ( "before remove_copy_if vc2: " , vc2) ;
auto it =
std:: remove_copy_if ( vc1. begin ( ) , vc1. end ( ) , std:: back_inserter ( vc2) , even) ;
print ( "after remove_copy_if vc1: " , vc1) ;
print ( "after remove_copy_if vc2: " , vc2) ;
}
before remove_copy_if vc1: 1 2 3 4 5 6 7 8 9
before remove_copy_if vc2:
after remove_copy_if vc1: 1 2 3 4 5 6 7 8 9
after remove_copy_if vc2: 1 3 5 7 9
七 std::unique
template < class ForwardIt >
ForwardIt unique ( ForwardIt first, ForwardIt last ) ; ( 1 ) ( C++ 20 前)
template < class ForwardIt >
constexpr ForwardIt unique ( ForwardIt first, ForwardIt last ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt >
ForwardIt unique ( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last ) ; ( 2 ) ( C++ 17 起)
template < class ForwardIt , class BinaryPredicate >
ForwardIt unique ( ForwardIt first, ForwardIt last, BinaryPredicate p ) ; ( 3 ) ( C++ 20 前)
template < class ForwardIt , class BinaryPredicate >
constexpr ForwardIt unique ( ForwardIt first, ForwardIt last, BinaryPredicate p ) ; ( 3 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt , class BinaryPredicate >
ForwardIt unique ( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
BinaryPredicate p ) ; ( 4 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc{ 1 , 2 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
print ( "before unique vc: " , vc) ;
auto it = std:: unique ( vc. begin ( ) , vc. end ( ) ) ;
print ( "after unique vc: " , vc) ;
print2 ( "after unique vc: " , vc. begin ( ) , it) ;
}
if ( 1 ) {
std:: vector< int > vc{ 1 , 2 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
print ( "before unique vc: " , vc) ;
auto it = std:: unique ( vc. begin ( ) , vc. end ( ) , my_equal) ;
print ( "after unique vc: " , vc) ;
print2 ( "after unique vc: " , vc. begin ( ) , it) ;
}
before unique vc: 1 2 2 2 3 3 4 5 6 7 8 9
after unique vc: 1 2 3 4 5 6 7 8 9 7 8 9
after unique vc: 1 2 3 4 5 6 7 8 9
before unique vc: 1 2 2 2 3 3 4 5 6 7 8 9
after unique vc: 1 2 3 4 5 6 7 8 9 7 8 9
after unique vc: 1 2 3 4 5 6 7 8 9
說明
通過用覆寫要被擦除的元素的方式遷移範圍中的元素進行移除。保持剩餘元素的相對順序,且不更改容器的物理大小。
另一個unique的詳細例子請參考此前文章 std::vector 去重。
八 std::unique_copy
template < class InputIt , class OutputIt >
OutputIt unique_copy ( InputIt first, InputIt last, OutputIt d_first ) ; ( 1 ) ( C++ 20 前)
template < class InputIt , class OutputIt >
constexpr OutputIt unique_copy ( InputIt first, InputIt last, OutputIt d_first ) ; ( 1 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt1 , class ForwardIt2 >
ForwardIt2 unique_copy ( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first ) ; ( 2 ) ( C++ 17 起)
template < class InputIt , class OutputIt , class BinaryPredicate >
OutputIt unique_copy ( InputIt first, InputIt last,
OutputIt d_first, BinaryPredicate p ) ; ( 3 ) ( C++ 20 前)
template < class InputIt , class OutputIt , class BinaryPredicate >
constexpr OutputIt unique_copy ( InputIt first, InputIt last,
OutputIt d_first, BinaryPredicate p ) ; ( 3 ) ( C++ 20 起)
template < class ExecutionPolicy , class ForwardIt1 , class ForwardIt2 , class BinaryPredicate >
ForwardIt2 unique_copy ( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first, BinaryPredicate p ) ; ( 4 ) ( C++ 17 起)
if ( 1 ) {
std:: vector< int > vc1{ 1 , 2 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
std:: vector< int > vc2;
print ( "before unique_copy vc1: " , vc1) ;
print ( "before unique_copy vc2: " , vc2) ;
auto it =
std:: unique_copy ( vc1. begin ( ) , vc1. end ( ) , std:: back_inserter ( vc2) ) ;
print ( "after unique_copy vc1: " , vc1) ;
print ( "after unique_copy vc2: " , vc2) ;
}
if ( 1 ) {
std:: vector< int > vc1{ 1 , 2 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
std:: vector< int > vc2;
print ( "before unique_copy vc1: " , vc1) ;
print ( "before unique_copy vc2: " , vc2) ;
auto it =
std:: unique_copy ( vc1. begin ( ) , vc1. end ( ) , std:: back_inserter ( vc2) , my_equal) ;
print ( "after unique_copy vc1: " , vc1) ;
print ( "after unique_copy vc2: " , vc2) ;
}
before unique_copy vc1: 1 2 2 2 3 3 4 5 6 7 8 9
before unique_copy vc2:
after unique_copy vc1: 1 2 2 2 3 3 4 5 6 7 8 9
after unique_copy vc2: 1 2 3 4 5 6 7 8 9
before unique_copy vc1: 1 2 2 2 3 3 4 5 6 7 8 9
before unique_copy vc2:
after unique_copy vc1: 1 2 2 2 3 3 4 5 6 7 8 9
after unique_copy vc2: 1 2 3 4 5 6 7 8 9
九 github
所有Demo 已上傳github cplusplus
removing_algorithm.cpp
十 參考