Google
 
Webnews.only-4-geeks.com
Interesting places
news.only-4-geeks.com Forum Index » C++

std::map<> or std::set<> as interval search tree

 
Jump to:  
 
Rune Allnor
PostPosted: Sun Aug 31, 2008 10:58 pm    Post subject: std::map<> or std::set<> as interval search tree
       
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map<>
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a>
and a value x > d returns a value indicating [d,inf>.

Any suggestions?

Rune

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Alberto Ganesh Barbati
PostPosted: Mon Sep 01, 2008 7:04 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
Rune Allnor ha scritto:
Quote:
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.

Any suggestions?


Looks like a job for the member function equal_range.

Ganesh

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
LR
PostPosted: Mon Sep 01, 2008 7:06 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
Rune Allnor wrote:
Quote:
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.



How many intervals do you have?
Are they all fixed width?
Do they change during the course of the program's execution?
How many searches will you have to do?

Depending on how many you have and how often they change, perhaps
storing the numbers in a vector and doing a modified binary search that
returns a std::pair that indicates where the number you're searching for
might fit.

If there are only a few numbers that change during execution then this
might still be acceptable.

This seems like a simple solution and might at least get you an
interface, you can always change the underlying code later if
performance is unacceptable.



However, if there are very many of your numbers or the numbers are very
likely to change during execution, then perhaps some sort of map of maps
of maps... might better fit the bill.

std::map<coarse_key, std::map<less_coarse, std::map<fine_key, value> > >

or maybe something like

class ValueOrMap {};
class Value : public ValueOrMap {};
class Map : public ValueOrMap {};

class ValueOrMapPointerWrapper {
ValueOrMap *p_;
....
};

std::map<coarse_key, ValueOrMapPointerWrapper>

I offer these suggestions as a point of departure, not a solution.

Also, it seems to me that in someways, your problem is not a C++ problem
and you might have better luck in an algorithms group.

LR



--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
David Abrahams
PostPosted: Mon Sep 01, 2008 7:14 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
on Sun Aug 31 2008, Rune Allnor <allnor-AT-tele.ntnu.no> wrote:

Quote:
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.

Any suggestions?

There's something called an "interval tree." IIRC it stores each
interval by its start position and annotates each node additionally with
the maximum end position of all its descendant nodes. I implemented one
years ago with minor modifications of STLPort's rbtree implementation
that underlay its associative containers. Ah, yes:
LINK

On the other hand, that's allows overlapping intervals, and it looks
like your example doesn't have overlaps. If not, you could use one of
the std associative containers (or a sorted vector) with a key that is
the beginning of each interval, and use upper_bound to find the position
where x falls in the sequence. I leave dealing with the endpoints as an
exercise for the reader ;-)

--
Dave Abrahams
BoostPro Computing
LINK

[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Tony Delroy
PostPosted: Mon Sep 01, 2008 7:20 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
On Sep 1, 7:58 am, Rune Allnor <all...@tele.ntnu.no> wrote:
Quote:
However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Read up on lower_bound() and upper_bound(). Note: there're both stand-
alone algorithm versions and container member function versions.

Quote:
Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.

Might have to special-case one or both of these, but no big deal.

HTH, Tony

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Scott McMurray
PostPosted: Mon Sep 01, 2008 10:18 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
On Aug 31, 6:58 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
Quote:
I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

[...]

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.

Any suggestions?


Do you need to store interval objects?

If not, it seems to me like you can do this perfectly by adding -
numeric_limits<T>::infinity(), numeric_limits<T>::infinity(), and all
the "fenceposts" (a, b, c, and d, here) to a set<T>. You can then
find the high end of the range using upper_bound, and the low end is
the previous iterator.

(You don't need the infinities either, but they save some special-
casing for getting end() and begin() from upper_bound, on the
assumption that the input is finite. Since you specified
[closed,open) ranges, upper_bound is used instead of lower_bound so
that the input-is-a-fencepost case works correctly.)

HTH,
~ Scott

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Rune Allnor
PostPosted: Mon Sep 01, 2008 10:58 am    Post subject: Re: std::map<> or std::set<> as interval search tree
       
On 1 Sep, 09:06, LR <lr...@superlink.net> wrote:
Quote:
Rune Allnor wrote:
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Note that I need to be able to locate numbers outside the present
limits, such that x < a returns some code indicating [-inf,a
and a value x > d returns a value indicating [d,inf>.

How many intervals do you have?

Unknown. Possibly as few as tens; maybe as many as tens of thousands.

Quote:
Are they all fixed width?

No.

Quote:
Do they change during the course of the program's execution?

Yes. The structure will be very dynamic; intervals will
change after every search. Each new x will split an existing
(internal) interval, and depending on other factors
surrounding intervals might be merged.

Quote:
How many searches will you have to do?

(Tens of) millions.

Quote:
Depending on how many you have and how often they change, perhaps
storing the numbers in a vector and doing a modified binary search that
returns a std::pair that indicates where the number you're searching for
might fit.

Somebody mentioned the upper_bound / lower_bound functions.
They seem to be good starting points.

Rune


--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Maxim Yegorushkin
PostPosted: Mon Sep 01, 2008 7:45 pm    Post subject: Re: std::map<> or std::set<> as interval search tree
       
On Aug 31, 11:58 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
Quote:
Hi all.

I have an application where the set of real numbers is divided into
a finite number of intervals (view with fixed-width font):

------------+---------+--------+---------+--------
a x b c d

Given a number x I would like to find the interval which contains x.
Searching for the interval is more efficient when a search tree
data structure is used, which is why I want to use std::map
or std::set<>. These implement tree-structures and if at all
possible, I would avoid to implement a tree from scratch myself.

However, both std::map and std::set will return an 'invalid' code
unless an item with the exact value of the search argument is
contained in the tree.

So given a number x, a < x < b, how do I implement the structure
such that a call to exists() returns a pointer to the interval
[a,b>? The pointer itself might be the value (or index or iterator) of
one of the end intervals; it has to be something that uniquely
identifies the interval where x belongs.

Here is a sketch:

~/src/test $ cat test.cpp
#include <set>
#include <cstdio>

struct interval
{
double start, end; // [start, end]
interval(double s, double e) : start(s), end(e) {}
};

bool operator<(interval const& a, interval const& b)
{
return a.start < b.start;
}

typedef std::set<interval> interval_set;

interval const* find(interval_set const& s, double point)
{
interval_set::const_iterator i = s.lower_bound(interval(point,
point));
if(i == s.end() || point < i->start) {
if(i == s.begin())
return NULL;
--i;
return point <= i->end && point >= i->start ? &*i : NULL;
}
return &*i;
}

void check(interval_set const& s, double point)
{
if(interval const* i = find(s, point))
printf("%f belongs to [%f,%f]\n", point, i->start, i->end);
else
printf("%f does not belong to any interval\n", point);
}

int main()
{
interval_set s;
s.insert(interval(0, 1));
s.insert(interval(3, 4));

for(double i = -1; i < 5; i += .5)
check(s, i);
}

~/src/test $ g++ -Wall -Wextra -o test test.cpp
~/src/test $ ./test
-1.000000 does not belong to any interval
-0.500000 does not belong to any interval
0.000000 belongs to [0.000000,1.000000]
0.500000 belongs to [0.000000,1.000000]
1.000000 belongs to [0.000000,1.000000]
1.500000 does not belong to any interval
2.000000 does not belong to any interval
2.500000 does not belong to any interval
3.000000 belongs to [3.000000,4.000000]
3.500000 belongs to [3.000000,4.000000]
4.000000 belongs to [3.000000,4.000000]
4.500000 does not belong to any interval

--
Max


[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
kalman
PostPosted: Thu Sep 18, 2008 9:28 pm    Post subject: Re: Is self assignment test valid?
       
On Sep 4, 3:58 am, Martin T <0xCDCDC...@gmx.at> wrote:
Quote:
Maciej Sobczak wrote:
On 2 Wrz, 06:40, gmr...@o2.pl wrote:
-----------------------
Is this example valid and have well defined behavior?

Yes (provided that "operations" make sense), but it is debatable
whether it is a good idiom.

The argument goes that if the reliability of the assignment operator
depends on the existence of the self-assignment-test, then the
operator most likely has some deeper design problems.
It is impossible to assert this for the code above, since the crucial
part ("operations") is not shown, but in practice this is very often
true - if you need this test, then you just try to protect something
that is inherently broken and even this protection is usually not
enough (hint: exception safety).

Examples would be nice.

I remember reading before that self assignemnt protection very often
hides some flaws, but I really fail to see the "very often".
For any object where it makes sense to use e.g. a memcpy in the
copy-ctor the self assignment test would tend to make the copying code
simpler and not only faster, no?

Performance optimization is the only potentially valid motivation for
such a test, but it actually improves the performance of a use case
that never happens (why assign to same object?) and therefore it does
not make any sense to optimize it.

Now that's quite a strong assumtion, is it not? "Never happens" is just
something that's bound to happen sooner or later :-)

Anyway - we (I) build redundancy into my code so that even with the
inevitable bugs it may just continue to run.

Both of you have a point here, what I'm used to using GCC is the usage
of likely/unliley macros
in order to give your compiler a branch prediction information, so you
operator becomes:

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

T& T::operator=(T const& rhs) {
if (likely(&rhs != this))
// operations
return *this;
}

Regards
Gaetano Mendola








--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

Page 1 of 1 .:.

Google
 
Webnews.only-4-geeks.com

Windows Update | C++ | C | PHP | JavaScript | Photoshop | Programming | Windows 2000 | Python | Windows XP | Object | Flash | Flash - ActionScript | Paint Shop Pro | Excel | PowerPoint | Access | Word | Windows 98 | Internet Explorer 6.0 | CorelDraw12 | Java | XML | asm x86 | Linux Mandrake | Linux RedHat | Outlook |  | news from newsgroups |_ | s

Web Templates

Awesome Website Templates ©

poker zasady gry apartamenty Åódź Obiektywy Nokia 7510 biznes