Hi All, I seem to remember reading about this [the subject of this post] in the docs, but I don't seem to be able to find it [that page] now. What criteria should I use to choose a specific Boost.Heap implementation (skew, fibonacci etc), from the ones provided by the Boost.Heap library? Thanks in advance and have a good day, degski
On 25 September 2016 at 17:07, degski
What criteria should I use to choose a specific Boost.Heap implementation (skew, fibonacci etc), from the ones provided by the Boost.Heap library?
Well, as no answer, wrote my own: #define BV_NOEXCEPT noexcept #define BV_CONST_NOEXCEPT const noexcept template < typename T > class priority_queue { private: typedef std::vector < T > Data; public: typedef typename Data::iterator iterator; typedef typename Data::const_iterator const_iterator; private: Data m_data; public: priority_queue ( ) BV_NOEXCEPT { m_data.reserve ( 16 ); } iterator begin ( ) BV_NOEXCEPT { return m_data.begin ( ); } const_iterator begin ( ) BV_CONST_NOEXCEPT { return m_data.begin ( ); } iterator end ( ) BV_NOEXCEPT { return m_data.end ( ); } const_iterator end ( ) BV_CONST_NOEXCEPT { return m_data.end ( ); } void push ( const T & t_ ) BV_NOEXCEPT { const const_iterator i = std::lower_bound ( m_data.begin ( ), m_data.end ( ), t_, std::greater < T > ( ) ); if ( i == m_data.end ( ) or std::greater < T > ( ) ( t_, * i ) ) { m_data.insert ( i, t_ ); } } inline void pop ( ) BV_NOEXCEPT { if ( m_data.size ( ) ) { m_data.pop_back ( ); } } inline T top ( ) BV_CONST_NOEXCEPT { return m_data.back ( ); } inline size_t size ( ) BV_CONST_NOEXCEPT { return m_data.size ( ); } inline bool empty ( ) BV_CONST_NOEXCEPT { return m_data.empty ( ); } }; Have a good day, degski
I am finding difficult to understand your answer, but I try to address the
following question:
>> *What criteria should I use to choose a specific Boost.Heap
implementation from the ones provided by the Boost.Heap library?*
Boost.Heap's data structures are documented here:
http://www.boost.org/doc/libs/1_61_0/doc/html/heap/data_structures.html
There is a simple table which shows the complexity for every public
function you may use. Just go through those functions and look for the ones
your are going to use the most and then choose the ones with less
complexity.
In most cases *fibonacci_heap* will be the best option... When in doubt,
just go for fibonacci_heap.
Best regards
Juan
On Tue, Sep 27, 2016 at 11:20 AM, degski
On 25 September 2016 at 17:07, degski
wrote: What criteria should I use to choose a specific Boost.Heap implementation (skew, fibonacci etc), from the ones provided by the Boost.Heap library?
Well, as no answer, wrote my own:
#define BV_NOEXCEPT noexcept #define BV_CONST_NOEXCEPT const noexcept
template < typename T > class priority_queue {
private:
typedef std::vector < T > Data;
public:
typedef typename Data::iterator iterator; typedef typename Data::const_iterator const_iterator;
private:
Data m_data;
public:
priority_queue ( ) BV_NOEXCEPT {
m_data.reserve ( 16 ); }
iterator begin ( ) BV_NOEXCEPT {
return m_data.begin ( ); }
const_iterator begin ( ) BV_CONST_NOEXCEPT {
return m_data.begin ( ); }
iterator end ( ) BV_NOEXCEPT {
return m_data.end ( ); }
const_iterator end ( ) BV_CONST_NOEXCEPT {
return m_data.end ( ); }
void push ( const T & t_ ) BV_NOEXCEPT {
const const_iterator i = std::lower_bound ( m_data.begin ( ), m_data.end ( ), t_, std::greater < T > ( ) );
if ( i == m_data.end ( ) or std::greater < T > ( ) ( t_, * i ) ) {
m_data.insert ( i, t_ ); } }
inline void pop ( ) BV_NOEXCEPT {
if ( m_data.size ( ) ) {
m_data.pop_back ( ); } }
inline T top ( ) BV_CONST_NOEXCEPT {
return m_data.back ( ); }
inline size_t size ( ) BV_CONST_NOEXCEPT {
return m_data.size ( ); }
inline bool empty ( ) BV_CONST_NOEXCEPT {
return m_data.empty ( ); } };
Have a good day,
degski
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Juan :wq
On 27 September 2016 at 17:57, Juan Ramírez
I am finding difficult to understand your answer, but I try to address the following question:
>> *What criteria should I use to choose a specific Boost.Heap implementation from the ones provided by the Boost.Heap library?*
Boost.Heap's data structures are documented here: http://www.boost.org/doc/libs/1_61_0/doc/html/heap/data_ structures.html
You've understood my question to a t. What I wanted was that link, but one don't get to that page from http://www.boost.org/doc/libs/1_61_0/doc/html/heap.html, which seems (to me) to be a (slight) problem. In the meanwhile I think I got (wrote) a better solution, as posted. Thanks for the post/response. Have a good day, degski
Hi,
You've understood my question to a t. What I wanted was that link, but one don't get to that page from http://www.boost.org/doc/libs/1_61_0/doc/html/heap.html, which seems (to me) to be a (slight) problem. In the meanwhile I think I got (wrote) a better solution, as posted. Thanks for the post/response.
Your solution has linear complexity, while the heaps provided have logarithmic complexity. (insertion in the middle of a vector is a linear time operation). That is hardly better. For your case, boost::heap::priority_queue is perfect.
On 27 September 2016 at 18:55, Oswin Krause wrote: Your solution has linear complexity, while the heaps provided have
logarithmic complexity. (insertion in the middle of a vector is a linear
time operation). Yes, of course it has linear complexity, but the factors are much smaller.
My test-case (which is more demanding than my use-case) with a (max heap)
size of about 50'000 beats any (more intelligent) solution heads down. I'll
just conclude with a quote: “In theory, theory and practice are the same.
In practice, they are not.”
Have a good day,
degski
It's actually log n.
Actually, it is not!!
Most functions have constant complexity, except for push, which is O(n+
log(n)) = O(n).
Let me explain:
1. std::lower_bound is logarithmic in N -> O( log(N) )
2. vector<T>::insert is linear in the number of elements of the vector ->
O(N)
vector<T>::insert is your bottleneck here:
* In the best case it will move all the elements at the right of the
element being inserted.
* In the worst case it will have to allocate a new array and the move ALL
the elements to the new location.
Best regards
Juan
On Tue, Sep 27, 2016 at 4:14 PM, degski
On 27 September 2016 at 18:55, Oswin Krause
de> wrote:
Your solution has linear complexity...
It's actually log n.
HAGD,
degski
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Juan :wq
On 27 September 2016 at 23:06, Juan Ramírez
vector<T>::insert is your bottleneck here:
You're absolutely right, if only inserting in a vector were cheap, life would be better. But like I said earlier, the constants (as compared to a heap or a set) are different... I timed my use-case and got an answer... Thanks for the feed-back, degski
Hi, On 2016-09-27 21:14, degski wrote:
On 27 September 2016 at 18:55, Oswin Krause
wrote: Your solution has linear complexity...
It's actually log n.
The worst case is insertion of objects with priority 1...n in that order. As your elements are sorted so that low priorities are on the right, your push function will always insert the new elements as the first element, thus all previously inserted elements are copied one element to the right(see complexity of std::vector::insert) => O(n) for every inserted elements and overall O(n^2/2) copies. Best, Oswin
Hi,
Yes, of course it has linear complexity, but the factors are much smaller. My test-case (which is more demanding than my use-case) with a (max heap) size of about 50'000 beats any (more intelligent) solution heads down. I'll just conclude with a quote: “In theory, theory and practice are the same. In practice, they are not.” When you have only 10 elements, you are free to do whatever you want, but as soon as you have a relevant amount, it is going to be hard to beat the std::heap because it is such an efficient data structure.
Have a nice day, Oswin
participants (3)
-
degski
-
Juan Ramírez
-
Oswin Krause