使用/不使用boost进行二进制搜索函数参数

时间:2013-08-02 15:37:46

标签: c++ boost c++03

鉴于:

typedef .../*some type*/ SomeValue;

SomeValue someFunction(int arg){
     return /*some calculation involving arg that produces SomeValue*/
}

int firstCandidate = 0, lastCandidate = 101;
SomeValue desiredValue = SomeValue();

我想找到int参数,它使用二分搜索(desiredValue)生成someFunction(传递给std::lower_bound时)。 firstCandidatelastCandidate是要赋予someFunction的参数。 对于搜索候选人std::lower_bound,应致电someFunction(currentArgument)并将结果与​​desiredValue进行比较。 SomeValue someFunction(x) < someFunction(x + 1)的确如此。

即。它应该产生与此相同的结果:

int findArgLowerbound(int first, int last, SomeValue refVal){
     for (int i = first; i < last; i++){
          if (someFunction(i) >= refVal)
               return i;
     }
     return last;
}

仅使用标准函数+二进制搜索算法。

如果有和没有提升,我怎么能 EASILY (没有编写我自己的二进制搜索功能)? int不是迭代器,在这种情况下我还没弄明白如何制作boost::make_transform_iterator

限制

  1. c ++ 03标准。
  2. 提升是可以的,但我真的更喜欢没有它的解决方案。
  3. - 编辑 -

    我想知道如何使用内置或已经可用的函数(std :: lower_bound和类似函数)做我想做的事情。我可以编写专门的二进制搜索功能,但我认为这不是“正确”的方法。

2 个答案:

答案 0 :(得分:0)

这就是我接近它的方式:

假装您有一个已排序的vector<SomeValue>。可以使用someFunction(index)访问此向量。

现在,look at this。这是二进制搜索的伪代码。继续上述思考过程,将A[imid]替换为someFunction(imid),将key改为SomeValue。确保SomeValue具有有效的operator <(或您使用的比较器功能代替它)。

这当然只适用于所有someFunction(x) < someFunction(x + 1)的{​​{1}}。你说这是真的,所以它应该是好的。

我建议使用迭代方法,因为它们都具有相同的渐近运行时,并且迭代版本可以更容易地报告未找到的密钥,并且倾向于使用更少的内存。

编辑我不知道使用x内容的简单方法。如上所述,std不能用作迭代器,并且您可能想要使用的所有函数都使用迭代器。 技术上但是,这些函数中的迭代器是模板化类型,因此您可以编写自己的int类或类似的东西。使用IntIter需要std::lower_boundoperator *()operator ++()operator +(int)可能会返回operator *(),其中someFunction(n)是与n关联的int值。但是, 我不知道这是否真的有效 ,可能需要更多时间和编码。如果你想采用这种方法,你应该看看std::lower_boundstd::advance(在IntIter中调用)。

答案 1 :(得分:0)

想通了(享受宏+模板伏都教)。

#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/irange.hpp>
#include <boost/typeof/std/utility.hpp>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <sstream>

std::string convertArgs(int arg1, int arg2){
    std::stringstream out;
    out << std::setfill('0') << std::setw(8) << arg1*arg2;
    return out.str();
}

void boostTest(){
    int first = 0, last = 42;
    int arg = 2;
    std::string desiredValue = "00000007";
    BOOST_AUTO(range, boost::irange(first, last));
    BOOST_AUTO(start, boost::make_transform_iterator(range.begin(), std::bind1st(std::ptr_fun(convertArgs), arg)));
    BOOST_AUTO(end, boost::make_transform_iterator(range.end(), std::bind1st(std::ptr_fun(convertArgs), arg)));
    BOOST_AUTO(found, std::lower_bound(start, end, desiredValue));
    if (found != end){
        std::cout << "str:" << *found << "\nval: " << *(found.base());
    }
}

int main(int argc, char** argv){
    boostTest();
    return 0;
}

最有可能的是,除非您生成具有所有可能值的数组,否则无法在没有增强的情况下轻松,自己制作包装器迭代器或类似的东西。