Re: [Algorithms] Cache-coherent hashing for broad-phase collision detection
Brought to you by:
vexxed72
|
From: Gino v. d. B. <gin...@gm...> - 2010-03-23 12:07:11
|
On 23-3-2010 10:34, Fabian Giesen wrote:
> Jon Watte schrieb:
>
>> <snip>
>> If you have buckets with zillions of items (a bad idea for other
>> reasons) and need to delete from the middle, try a std::list<> with a
>> custom allocator, or as others have said std::hash_map or similar.
>>
> Linked lists enforce a particular order. Whenever you have something
> that is just a "bucket of things" with no particular ordering
> requirements, a good option is to just use a std::vector<> (or, more
> generally, any array - this is not STL specific). To insert, you always
> use push_back. To remove a given item "x", you do:
>
> std::swap(x, container.back());
> container.pop_back();
>
> This doesn't preserve order, but it's simple, short and fast: insertion
> is amortized O(1) with std::vector semantics, and removal is guaranteed
> O(1).
I totally agree. Even with a custom allocator an std::list breaks cache
coherence and simply has too much overhead. I would not use std::swap
though, since x is a goner so no need to save it to back(). Instead do
std::vector<Entry>::iterator it;
...
Entry& x = *it; // it points to the item that needs to be destroyed, e.g.
// it = std::find(container.begin(), container.end(), victim);
x = container.back();
container.pop_back();
This saves you two writes since std::swap needs to create a temporary to
hold one of the swapped values. The extra writes are better avoided if
the size of Entry is huge or if it holds shared pointers.
> STL also offers this as an algorithm: there's std::remove and
> std::remove_if. Their usage is somewhat nonobvious: you do
>
> container.erase(std::remove(start, end), container.end());
>
> to remove everything in [start,end) in a "non-order-preserving" way, and
> similar with remove_if which uses a predicate.
>
> -Fabian
>
>
>
I think you mean
container.erase(std::remove(start, end, value), container.end());
since the STL remove takes three parameters. Furthermore std::remove
keeps the relative order intact.
http://www.cplusplus.com/reference/algorithm/remove/
At least, that is what I see in Visual C++ 8.0 (Sometimes they do adhere
to standards ;) Removing all values and leaving an unordered sequence
can be done using
std::vector<Entry>::iterator it = container.begin(), last = container.end();
while (it != last)
{
if (*it == value)
{
--last;
*it = *last;
}
else
{
++it;
}
}
container.erase(last, container.end());
Gino
|