I don't think I've ever had a situation where I've written code with a hashtable, and the structure has proved to have inherently unacceptable performance.
I don't think I've ever had a situation where I've written code with a balanced tree, and the structure has proved to have inherently unacceptable performance.
So I don't worry about it too much, and take the easy route. Python provides hash-based sets/dictionaries, so I use those. C++03 provides set
and map
but not unordered_set
and unordered_map
, so I use those. In languages/libraries where both are available, I use a tree if I need order, and a hashtable if (a) I don't need order, and (b) I have or can write a decent hash function. If I have a natural order already, but not a natural hash function, then of course the easy route is a tree.
In practice, the vast majority of associative arrays are keyed either on strings, integers, or tuples of those. So you always have an order, and a decent hash function isn't far off. If the one I'm using seems at all dodgy, it's therefore easy enough to try them both.
Radix trees are basically for cases where you expect long common prefixes. For example, if your keys are URLs of web pages, then somewhere between "almost all" and "all" of them are going to start with either http://
or https://
, with hostnames providing further common prefixes for sections of your tree. An obvious optimisation, therefore, is to avoid comparing that common prefix multiple times during a lookup, which indicates against a "plain" balanced tree. But as always, the "obvious" optimisation isn't necessarily worth the effort, unless you happen to have a library for it already to hand.