Nov 4, 2013 at 1:07am Nov 4, 2013 at 1:07am UTC
I've got a priority queue of items who, from time to time, returns a different comparison result.
Any way to re-sort a priority queue who is storing them?
Example:
1 2 3 4
#include <cstdlib>
struct Random {
bool operator <(const Random&) const { return !(rand()&1); }
};
Last edited on Nov 4, 2013 at 1:07am Nov 4, 2013 at 1:07am UTC
Nov 4, 2013 at 1:13am Nov 4, 2013 at 1:13am UTC
Ignoring that horrifying comparison operator, I think it's better to use a container that doesn't care about the order of its elements unless you manually sort it. Otherwise you're violating the container's requirements, which I think might be undefined behavior (I'm not sure though).
Last edited on Nov 4, 2013 at 1:15am Nov 4, 2013 at 1:15am UTC
Nov 4, 2013 at 1:25am Nov 4, 2013 at 1:25am UTC
It was purely as an example.
I'm going to give a try using a std::vector and std::make_heap/... as, from what I understood, that's what the priority_queue is using.
Nov 4, 2013 at 2:36am Nov 4, 2013 at 2:36am UTC
[edit]
DON'T DO THIS!
The comparison functor of a priority queue must be
stateless .
So OP is out of luck if he wants to apply a different comparison to the container. Just wrap your data in a new priority queue.
[/edit]
Off the top of my head:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
template <typename T>
struct MyPriorityCompare
{
enum { MODE_X, MODE_Y, MODE_Z } mode;
MyPriorityCompare(): mode( MODE_X ) { }
bool operator () ( const T& lhs, const T& rhs )
{
switch (mode)
{
case MODE_X: return lhs.x < rhs.x;
case MODE_Y: return lhs.y < rhs.y;
case MODE_Z: return lhs.z < rhs.z;
}
throw error? return default ?
}
};
1 2
MyPriorityCompare <3DPoint> mpc;
std::priority_queue <3DPoint, std::deque <3DPoint> , MyPriorityCompare <3DPoint> > priority_points;
1 2
mpc.mode = mpc.MODE_Y;
// I'm not sure ATM how to force priority queue to reorder. Call std::make_heap() on the contents?
Just a thought.
Last edited on Nov 4, 2013 at 3:12pm Nov 4, 2013 at 3:12pm UTC
Nov 4, 2013 at 1:32pm Nov 4, 2013 at 1:32pm UTC
Solved using lists and sorting elements on insertion, manually re-sorted when required.
Nov 4, 2013 at 3:03pm Nov 4, 2013 at 3:03pm UTC
Please tell me you didn't use std::list ;)
Nov 4, 2013 at 5:05pm Nov 4, 2013 at 5:05pm UTC
Thanks @ Duoas for the edit (The edit was more useful than the post itself :> )
@LB: I don't think std::list has any kind of big downsides in my situation, besides for the amount of new
calls.
Does std::list store the end pointer? Or does it travel all the way through every time?
Nov 4, 2013 at 5:35pm Nov 4, 2013 at 5:35pm UTC
@EssGeEich: nevermind, I misunderstood your post. std::list is good for inserting often.
Nov 4, 2013 at 6:55pm Nov 4, 2013 at 6:55pm UTC
> std::list is good for inserting often.
Not the best for priority-based insertion.
push_back() followed by std::push_heap() on std::vector<> would be faster.
And std::make_heap() on a vector (when the priorities change) would be faster than std::list<>::sort()
Nov 4, 2013 at 7:53pm Nov 4, 2013 at 7:53pm UTC
Ah, I guess vector wins in more cases than I thought :)
Nov 5, 2013 at 12:35am Nov 5, 2013 at 12:35am UTC
Alright, making a comparison test.
Pathfinding (100x100 map) Test:
Container | Time
std::list | 164ms
Reserved std::vector /make_heap | 290ms
std::vector /make_heap | 321ms
std::priority_queue | 355ms
Either I did something wrong, or I've been able to use a std::list in an optimal way.
Reserving more memory doesn't do the trick either, time goes down to around 290ms.
@JLBorges:
Making you notice a little detail anyways: Guess you noticed it.
Last edited on Nov 5, 2013 at 12:50am Nov 5, 2013 at 12:50am UTC