STL binary_search() implementation

STL binary_search() implementation

本文关键字:implementation search binary STL      更新时间:2023-10-16

'使用C++编程原理和实践'中的一个练习,要求实现STLbinary_search()函数。我使用递归做到了这一点,但程序不断抛出异常。因此,我决定查看解决方案,而我的实现中只缺少一件事。不幸的是,我无法理解为什么会这样。

/* binary search for containers with random_access_iterators */
template<class Iter, class T>
bool binary(Iter first, Iter last, const T& val)
{
if (first == last) return false;                                                        
Iter middle = first + (last - first) / 2; 
if (val == *middle) return true;
if (*middle < val /*??=>*/&& middle+1!=last/*<=??*/) return binary(middle, last, val);
if (*middle > val) return binary(first, middle, val);
return false;
}

为什么添加middle+1!=last?它有什么作用?

这是二叉搜索的特定实现中的特例。它被添加到此处,以便binary始终终止。

第二个if语句总是使间隔更短,因为middle总是严格小于last

然而,第一种if有时可以用相同的论点来称呼binary。具体来说,如果first == middle,可能会发生这种情况。这可能发生在last - first <= 1.这种情况发生在last - first == 1(如果last - first == 0,我们已经单独处理了这种情况(。这种情况发生在middle + 1 == last.

因此,笔者决定单独处理该案。如果发生这种情况并*middle < val,那么我们必须返回false,这正是该特定实现中将发生的情况:第二个if失败,最后一个return false工作。

这是相同的代码,为了更清晰而重写(恕我直言(:

template<class Iter, class T>
bool binary(Iter first, Iter last, const T& val)
{
if (first == last) return false;                                                        
Iter middle = first + (last - first) / 2; 
if (*middle < val) {
if (last - first == 1) {
return false;
} else {
// first < middle
return binary(middle, last, val);
}
} else if (*middle == val) {
return true;
} else {
// *middle > val
return binary(first, middle, val);
}
}

我个人认为该解决方案并不优雅,部分原因是这种奇怪的特殊情况,如果以稍微不同的方式重写函数,则可以避免这种情况。

例如,一项改进(在众多改进中(是从(middle + 1, last)进行第一次递归调用 -*middle < val,将middle包含在我们的搜索范围内是没有意义的。这也保证了终止

template<class Iter, class T>
bool binary(Iter first, Iter last, const T& val)
{
if (first == last) return false;                                                        
Iter middle = first + (last - first) / 2; 
if (*middle < val) {
return binary(middle + 1, last, val);
} else if (*middle == val) {
return true;
} else {
// *middle > val
return binary(first, middle, val);
}
}