Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select a random element in std::set in less than O(n) time?

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.

like image 766
BCS Avatar asked Nov 28 '11 20:11

BCS


People also ask

How do you select a random element in a set in C++?

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.


2 Answers

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.

like image 84
Victor Sorokin Avatar answered Nov 15 '22 14:11

Victor Sorokin


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.

like image 36
Derek Ledbetter Avatar answered Nov 15 '22 15:11

Derek Ledbetter