This question with an added constraint.
I'm willing to allow not-uniform selection as long as it's not to lop sided.
Given that "sets are typically implemented as binary search trees" and I expect they will contain some kind of depth or size information for balancing, I would expect you could do some sort of weighted random walk of the tree. However I don't know of any remotely portable way to do that.
Edit: The constraint is NOT for the amortized time.
To get a random element from a set first take a random number using rand() function then take a modulas (%) by set size so that our iterator will not go out of bounds. Now, to get random element just iterate idx=rand() % s. size() times to get random element.
Introduce array with size equal to set. Make array elements hold addresses of every element in set. Generate random integer R
bounded by array/set size, pick address in array's element indexed by R
and dereference it to obtain set's element.
I don't see how to do it with just std::set
, so you probably need a different data structure. Like Victor Sorokin said, you can combine a set with a vector. Instead of set<T>
, use map<T, size_t>
, plus vector< map<T, size_t>::iterator >
. The value for each key is an index into the vector, and each element of the vector points back to the map element. The vector elements have no particular order. When you add an element, put it at the end of the vector. When you remove an element and it's not the last one in the vector, move the last element to the deleted element's position.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With