πŸ‘€pedro84πŸ•‘5yπŸ”Ό244πŸ—¨οΈ43

(Replying to PARENT post)

And if you only need a monotone priority queue (i.e. priority queue where the popped elements are monotonically increasing/decreasing) you should consider using a radix heap. This monotone requirement can be satisfied more than you would expect when eg. using time as key or in pathfinding. I have a simple radix heap implementation here: https://github.com/mpdn/radix-heap
πŸ‘€noctuneπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

Like folks mentioned there, I wonder if a higher-fanout heap (people asked about 4-ary) might also do well in practice. Looking at Wikipedia (https://en.wikipedia.org/wiki/D-ary_heap), it looks like maybe so -- the growth in number of comparisons isn't that bad, and it mentions 4-ary heaps working well specifically.

(Like how linear search wins for small N, or insertion sort helps with small subarrays in introsort: more steps, but each step is also a lot cheaper on modern hardware due to fewer branch mispredictions, better cache locality, or something else that better fits the hardware's strengths.)

πŸ‘€twotwotwoπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

I have used a min-max heap once. I don't remember why I needed it at the time--it was a previous job--but I do remember that I had to roll my own, because it's just not that popular of a data structure, and it was the obvious and only good solution to the problem at the time.

So, it's nice to see a detailed analysis of the structure like this! Perhaps if it becomes more popular, I will find more places to use it.

πŸ‘€gliese1337πŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> "...C++20 finally added a way of accessing this instruction, using std::countl_zero. I don’t have C++20 though so I had to do it the old platform specific ways ..."

You don't need C++20. Even C++98 had std::bitset<>::count(), which has a nice conversion from unsigned long, and which, when compiled for SSE3 or better (e.g. Core2), uses a POPCNT instruction. It is pretty simple to produce various other results, including countl_zero, from a popcount, with just a couple of additional bitwise ops.

Modern compilers are happy to keep a bitset<32> in the same register as an unsigned long, so the conversion takes exactly zero cycles. POPCNT takes three cycles, and the extra bitwise ops another couple.

πŸ‘€ncmncmπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

In certain domains, the trend has been to give up constant factors in order to increase programmer productivity (e.g., python pays a 10x slowdown but is batteries included).

So in that case I would use this data structure even if it weren't faster. I can't count the number of times I have had to mess with inserting negative priorities into a min heap to create a max heap! We should just have one data structure that does both.

(though taking this idea to the logical extreme means we should just use Order Statistic Tree for everything since it not only gives you log(n) min/max, but also log(n) find kth and get rank of x)

πŸ‘€ghjπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

If you need a min-max heap (or double ended heap) in Go here is one I've used: https://github.com/aalpar/deheap

Very useful when you need it!

πŸ‘€nickcwπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

It would be neat to fire this up on an older processor which doesn’t have modern instruction-level parallelism and verify the difference in performance
πŸ‘€cellularmitosisπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

I've been using the author's flat_hash_map (https://github.com/skarupke/flat_hash_map) for several years now and have been really impressed. I've yet to find a single bug, it's nearly as fast as folly's hash maps (for my use case anyway) but far easier to integrate than folly.
πŸ‘€usefulcatπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

Impressive. Looking forward to the d-heap article.
πŸ‘€gpderettaπŸ•‘5yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

Wow. This is a very good analysis on a fundamental algorithm. Haven’t seen a high quality analysis like this for a good while.
πŸ‘€ww520πŸ•‘5yπŸ”Ό0πŸ—¨οΈ0