对带/不带提升的函数参数进行二分搜索
binary search over function arguments with/without boost
给定:
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
参数,它使用二进制搜索(std::lower_bound
(产生desiredValue
(当传递给someFunction
时(。 firstCandidate
,lastCandidate
是要给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;
}
仅使用标准函数+二叉搜索算法。
我如何在有和没有 boost 的情况下轻松做到这一点(无需编写自己的二叉搜索函数(? int
不是迭代器,在这种情况下我还没有弄清楚如何进行boost::make_transform_iterator
。
限制:
- C++03 标准。
- 提升是可以的,但我真的更喜欢没有它的解决方案。
--编辑--
我想知道如何使用内置或已经可用的函数(std::lower_bound 和类似函数(做我想做的事。我可以编写专门的二进制搜索函数,但我认为这不是"正确"的方法。
这是我的处理方式:
假设您有一个已排序的vector<SomeValue>
。可以使用someFunction(index)
访问此向量。
现在,看看这个。这是二进制搜索的伪代码。继续上面的思考过程,将A[imid]
替换为someFunction(imid)
,并使key
成为SomeValue
。确保SomeValue
具有有效的operator <
(或用于代替它的比较器函数(。
当然,这只有在someFunction(x) < someFunction(x + 1)
所有x
时才有效。你说这是真的,所以它应该是好的。
我建议使用迭代方法,因为两者都具有相同的渐近运行时,并且迭代版本可以更轻松地报告未找到的键,并且倾向于使用更少的内存。
编辑我不知道使用std
东西来做到这一点的简单方法。正如你上面提到的,int
不能用作迭代器,你可能想要使用的所有函数都需要迭代器。不过,从技术上讲,这些函数中的迭代器是模板化类型,因此您可以编写自己的IntIter
类或类似的东西。使用std::lower_bound
需要operator *()
、operator ++()
和operator +(int)
。 operator *()
可能会返回someFunction(n)
,其中n
是与IntIter
相关联的 int 值。但是,我不知道这是否真的有效,并且可能需要更多时间和编码。如果你想采用这种方法,你应该看看std::lower_bound
和std::advance
(在lower_bound
中称为(。
想通了(享受宏+模板巫毒教(。
#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;
}
最有可能的是,没有 boost 就无法轻松完成,除非您生成具有所有可能值的数组,自己制作包装迭代器或类似的东西。
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类