我目前正在考虑使用 std::binary_search()(来自库)来确定列表中是否存在某物的实例。在开始使用它之前,我想知道它是如何工作的。
我的理解是,它使用比较(对于用户定义的结构/类,它需要访问用户定义的比较函数)来找出列表/向量中是否存在对象的实例。根据本网站(http://www.cplusplus.com/reference/algorithm/binary_search/),使用的范围是:
[first, last)
那么它不包括最后一个,因为它必须将最后一个与最后一个 + 1 进行比较吗?
此外,用户定义的比较函数的逻辑也无关紧要,只要它区分对象/类中的属性即可。这是对的吗?
例如,如果我的结构/类由以下内容组成:
coord
{
int X;
int Y;
}
我必须确保我的比较函数以某种方式区分(以某种方式,例如大于/小于比较)列表/向量中元素 a 和 b 的 X 和 Y 属性。
std::binary_search() 是作为常见的二叉搜索算法实现的,它最多执行 log2(N)+1 元素比较。(有关如何实现二叉搜索的更多信息,请查看此链接)
那么它不包括最后一个,因为它必须将最后一个与最后一个 + 1 进行比较吗?
不,原因只是为了方便使用。您可以按以下方式调用该函数:
std::binary_search (v.begin(), v.end(), 42)
请注意,v.end() 将迭代器返回到序列末尾之后的元素。因此,它不指向任何元素,因此不应在搜索中进行评估。
此外,用户定义的比较函数的逻辑也无关紧要,只要它区分对象/类中的属性即可。这是对的吗?
它用于 binary_search() 的比较函数,以便知道您要查找的元素是否在当前正在测试的元素之前。换句话说,比较函数必须能够比较两个元素,如果第一个元素"低于"第二个元素(必须在第二个元素之前放置在容器中),则返回。
对于您的坐标示例,您可以编写一个比较器函数,如下所示:
struct lessThanKey
{
inline bool operator() (const Coord& lhs, const Coord& rhs)
{
return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
}
};
std::binary_search(v.begin(), v.end(), Coord{42, 42}, lessThanKey());
该范围不包括最后一个元素作为一般库约定,这意味着第一个和最后一个迭代器之间的距离等于该范围内的元素数,并且可以使用以下命令在循环中测试该范围:
while(first != last)
{
// process stuff
++first;
}
必须对使用相同(可能是用户定义的)比较函数排序的排序数据执行std::binary_search
。
该函数需要在两个元素之间建立小于关系。
struct coord
{
int x;
int y;
};
struct CoordComparator
{
bool operator()(const coord& lhs, const coord& rhs) const
{
return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;
}
};
std::vector<coord> v { {1, 1}, {2, 1}, {2, 2}, {1, 2} };
std::sort(v.begin(), v.end(), CoordComparator());
if(std::binary_search(v.begin(), v.end(), coord{2, 1}, CoordComparator()))
{
// element found in range
}
可以定义小于关系,以便报告较大的值小于较低的值,以提供反向排序关系。