【问题标题】:Why we need std::partition_point whereas we can use std::find_if_not algorithm?为什么我们需要 std::partition_point 而我们可以使用 std::find_if_not 算法?
【发布时间】:2021-11-11 20:45:04
【问题描述】:

这是我对算法std::partition_point 的可能实现:

template <typename In_It, typename FUNC>
In_It partitionPoint(In_It b, In_It e, FUNC pred){
    int len = e - b;

    while (len > 0){
        int half = len >> 1;
        In_It middle = b + half;
        if( pred(*middle) ){
            b = middle;
            ++b;
            len = len - half - 1;
        }
        else
            len = half;
    }
      return b;
}

除了使用std::distancetraits...之外,我的代码看起来像STL,因此它检查输入序列并返回一个迭代器,指向谓词成功的序列中的最后一个元素。换句话说,返回的迭代器表示一个不满足谓词的元素。

int main(){
    std::vector<int> v{1, 3, 5, 7, 9, 1, 3, 6, 8, 10, 12};
    auto it = partitionPoint(v.begin(), v.end(), [](int x){return x % 2; });

    if( it != v.cend() )
        std::cout << *it << " " << it - v.cbegin() << '\n';
}
  • 输出:

    6 at index: 7
    

没关系。但是为什么我不直接使用std::find_if_not,它将一个迭代器返回到谓词为假的第一个元素?

 auto it2 = findIfNot(v.cbegin(), v.cend(), [](int x){return x % 2; });
 if(it2 != v.cend())
    std::cout << *it2 << " at index: " << it2 - v.cbegin() << '\n';

输出:

  6 at index: 7

【问题讨论】:

  • 也许你可以使用它。可能还有其他算法可以用其他算法来表示。我建议看看你的编译器的实现,看看他们是否对std;:partition_point 使用了任何优化技巧。

标签: c++ algorithm


【解决方案1】:

std::find_if_not 具有 O(N) 复杂性,因为它进行线性遍历。另一方面,std::partition_point 具有O(logN) 的复杂性,因为它利用了集合被分区并执行二进制搜索来查找元素的事实。根据具体情况,这可能是一个巨大的性能胜利。

【讨论】:

  • 好的!我知道了。我错过了这一点!二进制搜索。非常感谢。
  • @ItachiUchiwa 不用担心。很高兴能提供帮助。
  • 非常感谢你总是那么乐于助人。事实上,出于理解和教育目的,我编写了许多模拟 STL 的算法。
猜你喜欢
  • 2016-03-14
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 2015-04-20
  • 2018-02-02
相关资源
最近更新 更多