How would I perform a find()
or lower_bound()
function on a std::set
using a comparator function that is independent of its key such that it still runs in O(log N) time?
Suppose I define a data type foo
with two variables x
and y
and have a std::set<foo>
that uses x
as the key value.
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;
Is it possible to perform a binary search using lower_bound()
or some other function that compares the values of y
?
For the sake of this argument, assume that x
and y
are unique and independent of each other, and that given two foo
variables foo1
and foo2
, if foo1.x < foo2.x
, then foo1.y < foo2.y
. This means that I cannot express y
as a function of x
, but is also ordered by y
within fooSetX
.
For example, given three foo(x,y)
values (2,5), (3,9) and (5,10) within fooSet
, a lower_bound()
that takes y = 7
as the search term would return an iterator pointing to (3,9).
Currently, the way I go about solving this is by having two std::set<foo>
s, ordered by x
and y
respectively. Whenever I need to search by y
, I use the second 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)