![](/img/trans.png)
[英]C++ Difference between std::lower_bound and std::set::lower_bound?
[英]C++ std::set with a custom lower_bound
如何使用独立于其键的比较器函数在std::set
上执行find()
或lower_bound()
函数,使其仍在O(log N)时间运行?
假设我定义了具有两个变量x
和y
的数据类型foo
,并具有一个将x
作为键值的std::set<foo>
。
struct foo {
int x, y;
foo(int x, int y) : x(x), y(y) {}
};
struct xCompare {
bool operator() (const foo& i, const foo& j) const {
return i.x < j.x;
}
};
// Within main()
std::set<foo, xCompare> fooSetX;
是否可以使用lower_bound()
或其他一些比较y
值的函数来执行二进制搜索?
为了这个参数,假设x
和y
是唯一且彼此独立的,并且给定两个foo
变量foo1
和foo2
,如果foo1.x < foo2.x
,则foo1.y < foo2.y
。 这意味着我不能将y
表示为x
的函数,但是在fooSetX
也由y
fooSetX
。
例如,给定fooSet
三个foo(x,y)
值(2,5),(3,9)和(5,10 lower_bound()
,将y = 7
作为搜索项的lower_bound()
将返回迭代器指向至(3,9)。
目前,我要解决此问题的方法是拥有两个std::set<foo>
,分别按x
和y
排序。 每当我需要按y
搜索时,我都使用第二个std::set
。
struct yCompare {
bool operator() (const foo& i, const foo& j) const {
return i.y < j.y;
}
};
// Within main()
std::set<foo, yCompare> fooSetY;
// Inserting elements
fooSetX.insert(foo(2,5)); fooSetY.insert(foo(2,5));
fooSetX.insert(foo(3,9)); fooSetY.insert(foo(3,9));
fooSetX.insert(foo(5,10)); fooSetY.insert(foo(5,10));
// lower_bound() with y = 7
std::set<foo>::iterator it = fooSetY.lower_bound(foo(0,7)); // points to (3,9)
您不能直接将自定义比较器传递给std::set::lower_bound
您需要将其传递给类模板本身,因为它将在内部用于维护对象的顺序(因此使std::set::lower_bound
工作) 。
这是std::set
模板的定义方式 :
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
Compare
是唯一的排序自定义点,它允许您提供一个函数对象 ,该函数对象将根据需要代替std::less<Key>
来比较您的对象。
无法将其他排序谓词添加到std::set
。
如果您希望对对象进行其他排序以实现O(log N)查找,则可以使用与原始对象保持同步的另一有序结构。 一个std::set
指向第一个使用不同比较器的对象的指针集可以工作。 例:
class MySet
{
private:
std::set<Item, Comparator0> _set0;
std::set<decltype(_set0.begin()), Comparator1> _set1;
public:
void insert(Item x)
{
auto res = _set0.insert(x);
assert(res.second);
_set1.insert(res.first);
}
const auto& lookup0(Key0 x) { return _set0.lower_bound(x); }
const auto& lookup1(Key1 x) { return *(_set1.lower_bound(x)); }
};
不使用std :: set,就像@Vittorio Romeo在他的答案中指出的那样。
有一个可以由不相关成员查找的boost数据结构 ,您可以定义为
struct foo {
int x, y;
foo(int x, int y) : x(x), y(y) {}
};
// helpers
struct x_tag {};
struct y_tag {};
boost::multi_index_container<
foo,
indexed_by<
ordered_unique<tag<x_tag>, boost::multi_index::member<foo, int, &foo::x>>, // std::less<int> applied to foo::x
ordered_unique<tag<y_tag>, boost::multi_index::member<foo, int, &foo::y>> // std::less<int> applied to foo::y
>
> fooSet;
int an_x, an_y;
// lookup by x
fooSet.get<x_tag>().find(an_x);
fooSet.get<y_tag>().find(an_y);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.