我需要一个与C ++ STL容器兼容的二进制搜索算法,比如标准库的std::binary_search
标头中的<algorithm>
,但我需要它来返回指向结果的迭代器,不是一个简单的布尔告诉我元素是否存在。
(另一方面,当他们为binary_search定义API时,标准委员会的想法到底是什么?!)
我主要担心的是我需要二进制搜索的速度,所以尽管我可以使用其他算法找到数据,如下所述,我想利用我的数据进行排序以获得好处的事实二进制搜索,而不是线性搜索。
到目前为止,lower_bound
和upper_bound
如果原点丢失则会失败:
//lousy pseudo code
vector(1,2,3,4,6,7,8,9,0) //notice no 5
iter = lower_bound_or_upper_bound(start,end,5)
iter != 5 && iter !=end //not returning end as usual, instead it'll return 4 or 6
注意:我也可以使用不属于std命名空间的算法,只要它与容器兼容即可。比方说,boost::binary_search
。
答案 0 :(得分:84)
没有此类功能,但您可以使用std::lower_bound
,std::upper_bound
或std::equal_range
编写一个简单的功能。
一个简单的实现可能是
template<class Iter, class T>
Iter binary_find(Iter begin, Iter end, T val)
{
// Finds the lower bound in at most log(last - first) + 1 comparisons
Iter i = std::lower_bound(begin, end, val);
if (i != end && !(val < *i))
return i; // found
else
return end; // not found
}
另一个解决方案是使用std::set
,它保证元素的排序,并提供一个方法iterator find(T key)
,它返回给定项的迭代器。但是,您的要求可能与集合的使用不兼容(例如,如果您需要多次存储相同的元素)。
答案 1 :(得分:8)
你应该看看std::equal_range
。它会将一对迭代器返回到所有结果的范围。
答案 2 :(得分:6)
有一组:
http://www.sgi.com/tech/stl/table_of_contents.html
搜索:
单独注意:
他们可能认为搜索容器可能会产生不止一个结果。但在奇怪的情况下,你只需要测试存在,优化版本也会很好。
答案 3 :(得分:3)
如果你喜欢std :: lower_bound太低级别,你可能想检查boost::container::flat_multiset。 它是使用二进制搜索实现为有序向量的std :: multiset的替代品。
答案 4 :(得分:1)
std :: lower_bound():)
答案 5 :(得分:1)
检查此功能,qBinaryFind:
RandomAccessIterator qBinaryFind ( RandomAccessIterator begin, RandomAccessIterator end, const T & value )
执行范围的二进制搜索 [开始,结束]并返回位置 价值的发生。如果有 没有出现价值,退货 端。
范围内的项目[开始,结束] 必须按升序排序;看到 的qsort()。
如果出现很多次 相同的价值,其中任何一个都可以 回。使用qLowerBound()或 qUpperBound()如果你需要更精细 控制。
示例:
QVector<int> vect; vect << 3 << 3 << 6 << 6 << 6 << 8; QVector<int>::iterator i = qBinaryFind(vect.begin(), vect.end(), 6); // i == vect.begin() + 2 (or 3 or 4)
该功能包含在<QtAlgorithms>
标题中,该标题是Qt库的一部分。
答案 6 :(得分:0)
返回范围内的位置的解决方案可能是这样的,只使用迭代器上的操作(即使迭代器不算术也应该有效):
template <class InputIterator, typename T>
size_t BinarySearchPos(InputIterator first, InputIterator last, const T& val)
{
const InputIterator beginIt = first;
InputIterator element = first;
size_t p = 0;
size_t shift = 0;
while((first <= last))
{
p = std::distance(beginIt, first);
size_t u = std::distance(beginIt, last);
size_t m = (p+u)/2;
std::advance(element, m - shift);
shift = m;
if(*element == val)
return m; // value found at position m
if(val > *element)
first = element++;
else
last = element--;
}
// if you are here the value is not present in the list,
// however if there are the value should be at position u
// (here p==u)
return p;
}
答案 7 :(得分:0)
int BinarySearch(vector<int> array,int var)
{
//array should be sorted in ascending order in this case
int start=0;
int end=array.size()-1;
while(start<=end){
int mid=(start+end)/2;
if(array[mid]==var){
return mid;
}
else if(var<array[mid]){
end=mid-1;
}
else{
start=mid+1;
}
}
return 0;
}
示例:考虑一个数组,A = [1,2,3,4,5,6,7,8,9] 假设您要搜索索引3 最初,start = 0和end = 9-1 = 8 现在,从开始&lt; =结束;中期= 4; (array [mid]是5)!= 3 现在,3位于mid的左侧,因为它小于5.因此,我们只搜索数组的左侧部分 因此,现在start = 0和end = 3; mid = 2.Since array [mid] == 3,因此我们得到了我们要搜索的数字。因此,我们返回其等于mid的索引。
答案 8 :(得分:0)
最短的实现,想知道为什么它不包含在标准库中:
template<class ForwardIt, class T, class Compare=std::less<>>
ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={})
{
// Note: BOTH type T and the type after ForwardIt is dereferenced
// must be implicitly convertible to BOTH Type1 and Type2, used in Compare.
// This is stricter than lower_bound requirement (see above)
first = std::lower_bound(first, last, value, comp);
return first != last && !comp(value, *first) ? first : last;
}