C++ 算法 区间的比较

一 概述
  • C++ 标准库中提供了很多算法,定义于头文件 < algorithm >。本文主要探究以下用于 区间比较 的算法:
    • equal 检验相等性
    • is_permutation(C++11) 测试不定序的相等性
    • mismatch 查找第一处不同
    • lexicographical_compare 字典次序比较
二 辅助函数
三 std::equal
  • 比较两个区间是否相等
  • 定义
    • std::equal 的定义式很多,也比较有代表性,挑出部分进行说明。大部分其他算法中,涉及到区间的表示,基本与 std::equal 类似,predicate是binary 或者 unary。
    • ExecutionPolicy 请参考此前文章 std::find std::execution。
    • predicate 请参考此前文章 C++ predicate。
// 第1个区间以[begin,end)表示 第2个区间以begin 或者[begin,end)表示
template< class InputIt1, class InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1,InputIt2 first2 );(until C++20)
template< class InputIt1, class InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, 
            InputIt2 last2 );(since C++14)(until C++20)

// 增加模板参数 ExecutionPolicy
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1,  
            ForwardIt2 first2 );(since C++17)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, 
            ForwardIt2 last2 );(since C++17)

// 增加模板参数 BinaryPredicate
template< class InputIt1, class InputIt2, class BinaryPredicate >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p );(until C++20)
template< class InputIt1, class InputIt2, class BinaryPredicate >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
            BinaryPredicate p );(since C++14)(until C++20)

// 增加模板参数 ExecutionPolicy 和 BinaryPredicate
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate >
bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
            BinaryPredicate p );(since C++17)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate >
bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, 
            ForwardIt2 last2, BinaryPredicate p );(since C++17)
......
  • Demo
std::vector<int> vc1;
std::vector<int> vc2;
std::vector<int> vc3;
std::vector<int> vc4;
fill(vc1, 1, 3);
fill(vc2, 1, 4);
fill(vc3, 1, 5);
fill(vc4, 1, 4);
print("vc1: ", vc1);
print("vc2: ", vc2);
print("vc3: ", vc3);
print("vc4: ", vc4);
std::cout << "vc1 and vc2 is " 
          << (std::equal(vc1.begin(), vc1.end(), vc2.begin(), vc2.end()) 
          ? "" : "not ") << "equal." << std::endl;
std::cout << "vc2 and vc3 is "
          << (std::equal(vc2.begin(), vc2.end(), vc3.begin()) 
          ? "": "not ") << "equal." << std::endl;
std::cout << "vc2 and vc3 is "
          << (std::equal(vc2.begin(), vc2.end(), vc3.begin(), vc3.end()) 
          ? "" : "not ") << "equal." << std::endl;
std::cout << "vc2 and vc4 is "
          << (std::equal(vc2.begin(), vc2.end(), vc4.begin(), my_equal)
          ? "" : "not ") << "equal." << std::endl;
// std::equal(vc3.begin(), vc3.end(), vc4.begin(), my_equal); 报错,vc3长度大于vc4
  • 结果
vc1: 1 2 3
vc2: 1 2 3 4
vc3: 1 2 3 4 5
vc4: 1 2 3 4
vc1 and vc2 is not equal.
vc2 and vc3 is equal.
vc2 and vc3 is not equal.
vc2 and vc4 is equal.
  • 说明
    • 注意第1区间长度不能大于第2区间;
三 std::is_permutation(C++11)
  • 两个区间是否具有相同的排列组合(permutation)
  • 定义
    • is_permutation定义式包含以下几种形式:(类似 std::equal)
      • 第1个区间以[begin,end)表示 第2个区间以begin 或者[begin,end)表示
      • 增加模板参数 BinaryPredicate的形式
  • Demo
std::vector<int> vc1{3,2,1};
std::vector<int> vc2;
std::vector<int> vc3;
std::vector<int> vc4{4,2,1,3};
fill(vc2, 1, 4);
fill(vc3, 1, 5);
print("vc1: ", vc1);
print("vc2: ", vc2);
print("vc3: ", vc3);
print("vc4: ", vc4);
std::cout << "vc1 and vc2 is "
          << (std::is_permutation(vc1.begin(), vc1.end(), vc2.begin(), vc2.end()) 
          ? "" : "not ") << "equal." << std::endl;
std::cout << "vc2 and vc3 is "
          << (std::is_permutation(vc2.begin(), vc2.end(), vc3.begin())
          ? "" : "not ") << "equal." << std::endl;
std::cout << "vc2 and vc3 is "
          << (std::is_permutation(vc2.begin(), vc2.end(), vc3.begin(), vc3.end()) 
          ? "" : "not ") << "equal." << std::endl;
std::cout << "vc3 and vc4 is "
          << (std::is_permutation(vc2.begin(), vc2.end(), vc4.begin(), my_equal) 
          ? "" : "not ") << "equal." << std::endl;
//  std::cout << "vc3 and vc4 is "
//            << (std::is_permutation(vc3.begin(), vc3.end(), vc4.begin(), my_equal) 
//            ? "" : "not ") << "equal." << std::endl; 报错,vc3长度大于vc4
  • 结果
vc1: 3 2 1
vc2: 1 2 3 4
vc3: 1 2 3 4 5
vc4: 4 2 1 3
vc1 and vc2 is not equal.
vc2 and vc3 is equal. // 结果1
vc2 and vc3 is not equal. // 结果2
vc3 and vc4 is equal.
  • 说明
    • 若第2区间仅以begin表示,则只比较到第1区间结尾为止,例如 “结果1”;
    • 若第2区间以[begin,end)表示,则比较的是完整的第1区间和第2区间,例如 “结果2”;
    • 注意第1区间长度不能大于第2区间;
四 std::mismatch
  • 定义
    • mismatch定义式类似 std::equal
    • 注意返回值为pair
template< class InputIt1, class InputIt2 >
std::pair<InputIt1,InputIt2>
    mismatch( InputIt1 first1, InputIt1 last1, InputIt2 first2 );
  • Demo
std::vector<int> vc1{3, 2, 1};
std::vector<int> vc2;
std::vector<int> vc3;
std::vector<int> vc4{4, 2, 1, 3};
fill(vc2, 1, 4);
fill(vc3, 1, 5);
print("vc1: ", vc1);
print("vc2: ", vc2);
print("vc3: ", vc3);
print("vc4: ", vc4);

auto pair1 = std::mismatch(vc1.begin(), vc1.end(), vc2.begin());
std::cout << "vc1 and vc2 mismatch: No." << std::distance(vc1.begin(), pair1.first)
          << " : No." << std::distance(vc2.begin(), pair1.second) << std::endl;

auto pair11 = std::mismatch(vc1.begin(), vc1.end(), vc2.begin(), my_equal);
std::cout << "vc1 and vc2 mismatch: No."
          << std::distance(vc1.begin(), pair11.first) << " : No."
          << std::distance(vc2.begin(), pair11.second) << std::endl;

auto pair2 = std::mismatch(vc2.begin(), vc2.end(), vc3.begin(), vc3.end());
std::cout << "vc2 and vc3 mismatch: No."
          << std::distance(vc2.begin(), pair2.first) << " : No."
          << std::distance(vc3.begin(), pair2.second) << std::endl;

auto pair22 = std::mismatch(vc2.begin(), vc2.end(), vc3.begin(), vc3.end(), my_equal);
std::cout << "vc2 and vc3 mismatch: No."
          << std::distance(vc2.begin(), pair22.first) << " : No."
          << std::distance(vc3.begin(), pair22.second) << std::endl;

auto pair3 = std::mismatch(vc3.begin(), vc3.end(), vc4.begin(), vc4.end(), my_equal);
std::cout << "vc3 and vc4 mismatch: No."
           << std::distance(vc3.begin(), pair3.first) << " : No."
          << std::distance(vc4.begin(), pair3.second) << std::endl; 

 auto pair4 = std::mismatch(vc3.begin(), vc3.end(), vc2.begin(), vc2.end(), my_equal);
 std::cout << "vc3 and vc2 mismatch: No."
           << std::distance(vc3.begin(), pair4.first) << " : No."
           << std::distance(vc2.begin(), pair4.second) << std::endl;
  • 结果
vc1: 3 2 1
vc2: 1 2 3 4
vc3: 1 2 3 4 5
vc4: 4 2 1 3
vc1 and vc2 mismatch: No.0 : No.0
vc1 and vc2 mismatch: No.0 : No.0
vc2 and vc3 mismatch: No.4 : No.4 // 结果1
vc2 and vc3 mismatch: No.4 : No.4
vc3 and vc4 mismatch: No.0 : No.0
vc3 and vc2 mismatch: No.4 : No.4 // 结果2
  • 说明
    • 结果1和2说明对区间长度没有要求(demo 为windows下运行)。没有不同,则较短区间返回end()和另一序列对应元素迭代器组成pair返回。
    • 没有找到不同,不代表区间相同,例如结果1, vc3比vc2元素多。
五 std::lexicographical_compare
  • lexicographical:字典次序
  • 定义
    • lexicographical_compare定义式包含以下几种形式:(类似 std::equal)
      • 第1个区间以[begin,end)表示 第2个区间以 [begin,end) 表示
      • 增加模板参数 ExecutionPolicy
      • 增加模板参数 Compare
      • 增加模板参数 ExecutionPolicy 和 Compare
  • Demo
std::vector<int> vc1{3, 2, 1};
std::vector<int> vc2;
std::vector<int> vc3;
std::vector<int> vc4{4, 2, 1, 3};
fill(vc2, 1, 4);
fill(vc3, 1, 5);
print("vc1: ", vc1);
print("vc2: ", vc2);
print("vc3: ", vc3);
print("vc4: ", vc4);

std::cout << "vc1 lexicographical "
          << (std::lexicographical_compare(vc1.begin(), vc1.end(), vc2.begin(), vc2.end())
                  ? "" : "not ")  << "less than vc2 ." << std::endl;
std::cout << "vc2 lexicographical "
          << (std::lexicographical_compare(vc2.begin(), vc2.end(),
                                           vc3.begin(), vc3.end(), std::greater<int>())
          ? "" : "not ") << "less than vc3 ." << std::endl;
std::cout << "vc3 lexicographical "
          << (std::lexicographical_compare(vc3.begin(), vc3.end(),vc2.begin(), vc2.end(), 
                                           std::greater<int>())
           ? "" : "not ") << "less than vc2 ." << std::endl;
std::cout << "vc3 lexicographical "
          << (std::lexicographical_compare(vc3.begin(), vc3.end(), vc4.begin(), vc4.end(), 
                                           std::greater<int>())
          ? ""  : "not ") << "less than vc4 ." << std::endl;
  • 结果
vc1: 3 2 1
vc2: 1 2 3 4
vc3: 1 2 3 4 5
vc4: 4 2 1 3
vc1 lexicographical not less than vc2 .
vc2 lexicographical less than vc3 . // 结果1
vc3 lexicographical not less than vc2 . // 结果2
vc3 lexicographical not less than vc4 .
  • 说明
    • 结果1和2说明对区间长度没有要求(demo 为windows下运行)。
    • 共有的元素都相等,则元素数少的区间小于另一序列,例如 “结果1”。
六 参考
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用C++实现贪心算法解决区间调度问题的示例代码: ```cpp #include <iostream> #include <vector> #include <algorithm> // 区间结构体 struct Interval { int start; int end; }; // 比较函数,根据结束时间排序 bool compareIntervals(Interval a, Interval b) { return a.end < b.end; } // 贪心算法解决区间调度问题 int intervalScheduling(std::vector<Interval>& intervals) { // 按照结束时间排序 std::sort(intervals.begin(), intervals.end(), compareIntervals); int count = 1; // 最少需要一个区间 int endTime = intervals[0].end; // 遍历区间,选择结束时间最早的不冲突区间 for (int i = 1; i < intervals.size(); i++) { if (intervals[i].start >= endTime) { count++; endTime = intervals[i].end; } } return count; } int main() { std::vector<Interval> intervals = {{1, 3}, {2, 4}, {3, 6}, {5, 7}, {6, 8}}; int result = intervalScheduling(intervals); std::cout << "最多可安排的任务数量: " << result << std::endl; return 0; } ``` 在这个示例中,我们定义了一个`Interval`结构体来表示区间,并实现了一个比较函数`compareIntervals`,用于根据结束时间对区间进行排序。`intervalScheduling`函数使用贪心算法解决区间调度问题,首先对区间按照结束时间进行排序,然后从第一个区间开始遍历,选择结束时间最早的不冲突区间,并计数。最后输出最多可安排的任务数量。 在主函数中,我们创建了一个包含几个区间的示例输入,然后调用`intervalScheduling`函数计算结果,并输出最多可安排的任务数量。 注意:这只是一个简单的示例,实际问题可能需要根据具体情况进行更复杂的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值