一 概述
- C++ 标准库中提供了很多算法,定义于头文件 < algorithm >。本文主要探究以下用于 已排序区间 的算法:
- std::binary_search 查找元素是否存在于某范围中
- std::includes 范围是否包含另一范围
- std::lower_bound 返回指向第一个不小于给定值的元素的迭代器
- std::upper_bound 返回指向第一个大于给定值的元素的迭代器
- std::equal_range 返回匹配特定键值的元素范围
- std::merge 归并两个已排序区间到一个已排序区间
- std::set_union 计算并集
- std::set_intersection 计算交集
- std::set_difference 计算差集
- std::set_symmetric_difference 计算对称差
- std::inplace_merge 归并两个相继已排序区间到一个排序区间(稳定排序)
- std::partition_point 定位已划分范围的划分点
二 辅助函数
三 std::binary_search
template< class ForwardIt, class T >
bool binary_search( ForwardIt first, ForwardIt last, const T& value );(1)(until C++20)
template< class ForwardIt, class T >
constexpr bool binary_search( ForwardIt first, ForwardIt last, const T& value );(1)(since C++20)
template< class ForwardIt, class T, class Compare >
bool binary_search( ForwardIt first, ForwardIt last, const T& value, Compare comp );(2)(until C++20)
template< class ForwardIt, class T, class Compare >
constexpr bool binary_search( ForwardIt first, ForwardIt last, const T& value,
Compare comp );(2)(since C++20)
if (1) {
std::vector<int> vc;
fill(vc, 1, 6);
print("vc: ", vc);
std::cout << "find 6 in vc: " << std::boolalpha << std::binary_search(vc.begin(), vc.end(), 6) << std::endl;
std::cout << "find 7 in vc: " << std::boolalpha << std::binary_search(vc.begin(), vc.end(), 7) << std::endl;
}
vc: 1 2 3 4 5 6
find 6 in vc: true
find 7 in vc: false
四 std::includes
template< class InputIt1, class InputIt2 >
bool includes( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2 );(1)(until C++20)
template< class InputIt1, class InputIt2 >
constexpr bool includes( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2 );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
bool includes( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2 );(2)(since C++17)
template< class InputIt1, class InputIt2, class Compare >
bool includes( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2, class Compare >
constexpr bool includes( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class Compare >
bool includes( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc;
fill(vc, 1, 6);
std::vector<int> vc1;
fill(vc1, 2, 4);
std::vector<int> vc2;
fill(vc2, 3, 7);
print("vc: ", vc);
print("vc1: ", vc1);
print("vc2: ", vc2);
std::cout << "vc1 in vc: " << std::boolalpha
<< std::includes(vc.begin(), vc.end(), vc1.begin(), vc1.end()) << std::endl;
std::cout << "vc2 in vc: " << std::boolalpha
<< std::includes(vc.begin(), vc.end(), vc2.begin(), vc2.end()) << std::endl;
}
vc: 1 2 3 4 5 6
vc1: 2 3 4
vc2: 3 4 5 6 7
vc1 in vc: true
vc2 in vc: false
五 std::lower_bound
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );(1)
(until C++20)
template< class ForwardIt, class T >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );(1)
(since C++20)
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value, Compare comp );(2)
(until C++20)
template< class ForwardIt, class T, class Compare >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value,
Compare comp );(2)(since C++20)
if (1) {
std::vector<int> vc{1,3,5,7};
print("vc: ", vc);
std::cout << "lower_bound 5 in vc: "
<< *std::lower_bound(vc.begin(), vc.end(), 5) << std::endl;
}
vc: 1 3 5 7
lower_bound 5 in vc: 5
六 std::upper_bound
template< class ForwardIt, class T >
ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value );(1)(until C++20)
template< class ForwardIt, class T >
constexpr ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value );(1)(since C++20)
template< class ForwardIt, class T, class Compare >
ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value,
Compare comp );(2)(until C++20)
template< class ForwardIt, class T, class Compare >
constexpr ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value,
Compare comp );(2)(since C++20)
if (1) {
std::vector<int> vc{1, 3, 5, 7};
print("vc: ", vc);
std::cout << "upper_bound 5 in vc: "
<< *std::upper_bound(vc.begin(), vc.end(), 5) << std::endl;
}
vc: 1 3 5 7
upper_bound 5 in vc: 7
七 std::equal_range
template< class ForwardIt, class T >
std::pair<ForwardIt,ForwardIt>
equal_range( ForwardIt first, ForwardIt last,
const T& value );(1)(until C++20)
template< class ForwardIt, class T >
constexpr std::pair<ForwardIt,ForwardIt>
equal_range( ForwardIt first, ForwardIt last,
const T& value );(1)(since C++20)
template< class ForwardIt, class T, class Compare >
std::pair<ForwardIt,ForwardIt>
equal_range( ForwardIt first, ForwardIt last,
const T& value, Compare comp );(2)(until C++20)
template< class ForwardIt, class T, class Compare >
constexpr std::pair<ForwardIt,ForwardIt>
equal_range( ForwardIt first, ForwardIt last,
const T& value, Compare comp );(2)(since C++20)
if (1) {
std::vector<int> vc{1, 3, 5, 7};
print("vc: ", vc);
auto p = std::equal_range(vc.begin(), vc.end(), 5);
std::cout << "equal_range 5 in vc first pos: "
<< std::distance(vc.begin(), p.first) << std::endl;
std::cout << "equal_range 5 in vc end pos: "
<< std::distance(vc.begin(), p.second) << std::endl;
}
equal_range 5 in vc first pos: 2
equal_range 5 in vc end pos: 3
八 std::merge
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt merge( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt >
constexpr OutputIt merge( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 merge( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first );(2)(since C++17)
template< class InputIt1, class InputIt2, class OutputIt, class Compare>
OutputIt merge( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt, class Compare>
constexpr OutputIt merge( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3, class Compare>
ForwardIt3 merge( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc1{1, 3, 5, 7};
print("vc1: ", vc1);
std::vector<int> vc2{2, 4, 6, 8};
print("vc2: ", vc2);
std::vector<int> vc3;
print("vc3: ", vc3);
auto p = std::merge(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(), std::back_inserter(vc3));
std::cout << "merge vc1 and vc2 to vc3: "<< std::endl;
print("vc3: ", vc3);
}
vc1: 1 3 5 7
vc2: 2 4 6 8
vc3:
merge vc1 and vc2 to vc3:
vc3: 1 2 3 4 5 6 7 8
九 std::set_union
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_union( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt >
constexpr OutputIt set_union( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_union( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first );(2)(since C++17)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
OutputIt set_union( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
constexpr OutputIt set_union( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class Compare >
ForwardIt3 set_union( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc1{1, 3, 5, 7};
print("vc1: ", vc1);
std::vector<int> vc2{2, 4, 6, 8};
print("vc2: ", vc2);
std::vector<int> vc3;
print("vc3: ", vc3);
auto p = std::set_union(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(),
std::back_inserter(vc3));
std::cout << "set_union vc1 and vc2 to vc3: " << std::endl;
print("vc3: ", vc3);
}
vc1: 1 3 5 7
vc2: 2 4 6 8
vc3:
set_union vc1 and vc2 to vc3:
vc3: 1 2 3 4 5 6 7 8
十 std::set_intersection
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_intersection( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt >
constexpr OutputIt set_intersection( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_intersection( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first );(2)(since C++17)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
OutputIt set_intersection( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
constexpr OutputIt set_intersection( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class Compare >
ForwardIt3 set_intersection( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc1{1, 2, 3, 5, 7};
print("vc1: ", vc1);
std::vector<int> vc2{2, 4, 6, 8};
print("vc2: ", vc2);
std::vector<int> vc3;
print("vc3: ", vc3);
auto p = std::set_intersection(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(),
std::back_inserter(vc3));
std::cout << "set_intersection vc1 and vc2 to vc3: " << std::endl;
print("vc3: ", vc3);
}
vc1: 1 2 3 5 7
vc2: 2 4 6 8
vc3:
set_intersection vc1 and vc2 to vc3:
vc3: 2
十一 std::set_difference
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt >
constexpr OutputIt set_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_difference( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first );(2)(since C++17)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
OutputIt set_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
constexpr OutputIt set_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class Compare >
ForwardIt3 set_difference( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc1{1, 2, 3, 5, 7};
print("vc1: ", vc1);
std::vector<int> vc2{2, 4, 6, 8};
print("vc2: ", vc2);
std::vector<int> vc3;
print("vc3: ", vc3);
auto p = std::set_difference(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(),
std::back_inserter(vc3));
std::cout << "set_difference vc1 and vc2 to vc3: " << std::endl;
print("vc3: ", vc3);
}
vc1: 1 2 3 5 7
vc2: 2 4 6 8
vc3:
set_difference vc1 and vc2 to vc3:
vc3: 1 3 5 7
十二 std::set_symmetric_difference
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_symmetric_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(until C++20)
template< class InputIt1, class InputIt2, class OutputIt >
constexpr OutputIt set_symmetric_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );(1)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_symmetric_difference( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first );(2) (since C++17)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
OutputIt set_symmetric_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(until C++20)
template< class InputIt1, class InputIt2,
class OutputIt, class Compare >
constexpr OutputIt set_symmetric_difference( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first, Compare comp );(3)(since C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class Compare >
ForwardIt3 set_symmetric_difference( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,
ForwardIt3 d_first, Compare comp );(4)(since C++17)
if (1) {
std::vector<int> vc1{1, 2, 3, 5, 7};
print("vc1: ", vc1);
std::vector<int> vc2{2, 4, 6, 8};
print("vc2: ", vc2);
std::vector<int> vc3;
print("vc3: ", vc3);
auto p = std::set_symmetric_difference(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(),
std::back_inserter(vc3));
std::cout << "set_symmetric_difference vc1 and vc2 to vc3: " << std::endl;
print("vc3: ", vc3);
}
vc1: 1 2 3 5 7
vc2: 2 4 6 8
vc3:
set_symmetric_difference vc1 and vc2 to vc3:
vc3: 1 3 4 5 6 7 8
- 说明
- 数学上,两个集合的对称差是只属于其中一个集合,而不属于另一个集合的元素组成的集合。
十三 std::inplace_merge
template< class BidirIt >
void inplace_merge( BidirIt first, BidirIt middle, BidirIt last );(1)
template< class ExecutionPolicy, class BidirIt >
void inplace_merge( ExecutionPolicy&& policy, BidirIt first,
BidirIt middle, BidirIt last );(2)(since C++17)
template< class BidirIt, class Compare>
void inplace_merge( BidirIt first, BidirIt middle, BidirIt last, Compare comp );(3)
template< class ExecutionPolicy, class BidirIt, class Compare>
void inplace_merge( ExecutionPolicy&& policy, BidirIt first, BidirIt middle,
BidirIt last, Compare comp );(4)(since C++17)
if (1) {
std::vector<std::pair<int, string>> vc{
{1, "tom"}, {3, "lee"}, {1, "john"}, {5, "kate"}};
for(auto item : vc) {
std::cout << "{" << item.first << ", " << item.second << "}" << std::endl;
}
std::inplace_merge(vc.begin(), vc.begin() + 2, vc.end());
std::cout << "after inplace_merge: " << std::endl;
for (auto item : vc) {
std::cout << "{" << item.first << ", " << item.second << "}" << std::endl;
}
}
{1, tom}
{3, lee}
{1, john}
{5, kate}
after inplace_merge:
{1, john}
{1, tom}
{3, lee}
{5, kate}
十四 std::partition_point
template< class ForwardIt, class UnaryPredicate >
ForwardIt partition_point( ForwardIt first, ForwardIt last,
UnaryPredicate p );(since C++11)(until C++20)
template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition_point( ForwardIt first, ForwardIt last,
UnaryPredicate p );(since C++20)
if (1) {
std::vector<int> vc;
fill(vc, 1, 6);
print("vc: ", vc);
std::partition(vc.begin(), vc.end(), even);
print("vc: ", vc);
auto it = std::partition_point(vc.begin(), vc.end(), even);
std::cout << "partition_point vc of noteven: " << std::distance(vc.begin(), it)
<< std::endl;
}
vc: 1 2 3 4 5 6
vc: 6 2 4 3 5 1
partition_point vc of noteven: 3
十五 github
- 所有Demo 已上传github cplusplus
- sorted-range_algorithm.cpp
十六 参考