Этот вопрос связан с этот , а точнее этот ответ на него.
Вот и: у меня есть unordered_set C ++ / TR1 U
целых чисел без знака (приблизительная мощность 100-50000, приблизительный диапазон значений от 0 до 10 ^ 6).
Учитывая мощность N
, я хочу как можно быстрее перебрать N
случайным образом, но
уникальные члены U
. Типичного значения для N
нет, но оно должно
работают быстро для малых N
.
Более подробно, понятие "случайность" здесь
что два вызова должны давать несколько разные подмножества - тем более разные,
тем лучше, но это не так уж важно. Я, например, был бы доволен непрерывным
(или непрерывно с обертыванием)
блок из N
членов U
, пока начальный индекс блока является случайным.
Лучше прерывание по той же цене, но главное беспокойство - скорость. U
изменения
мягко, но постоянно между вызовами (примерно 0-10 элементов вставляются / стираются между вызовами).
Как далеко я зашел:
Тривиальный подход:
Выбрать случайный индекс i
такой что (i + N-1) .
Получите итератор
it
в U.begin ()
, продвиньте его i
раз, используя it ++
, а затем запустите
фактический цикл по подмножеству. Преимущество: легко. Недостаток: трата ++.
Подход ведра (и это я "недавно" извлек из приведенной выше ссылки):
Выберите i
, как указано выше, найдите сегмент b
, в котором находится i
-й элемент, получите local_iterator горит
до U.begin (b)
, продвижение горит
через горит ++
, пока мы не достигнем i
-го элемента U
, и с этого момента продолжайте увеличивать , горит
N
раз. Если мы дойдем до конца ведра,
мы продолжаем с горит
с начала следующего ведра. Если я хочу это сделать
более случайный. Я могу выбрать и
полностью случайным образом и обернуть его по корзинам.
Мои открытые вопросы:
U
, как только я найду i
-й элемент? Это пощадит меня
контроль границ ковша и т. д. Для меня как
новичку кажется непостижимым, что стандартный итератор вперед должен знать, как
продолжить обход U
, когда на i
-й элемент, но когда я сам нашел i
-й элемент,
не должно быть возможности пройти U
, кроме как через пункт 2.