Как насчет этого:
Пусть n
= количество элементов , list
= массив элементов , watermark
: = 0.
r := random()
i := floor(r * n)
if i >= watermark :
index := i
watermark := watermark + 1 // weighted part grows
else :
index := floor(weight(r * n / watermark) * watermark)
endif
move list[index] to list[0] // shifting elements list[0..index-1] up one place
result := list[0]
Здесь мы делим список на две части, взвешенные и однородные, с границей, отслеживаемой watermark
. Первоначально взвешенная часть пуста, но постепенно она увеличивается, в конце концов занимая весь список.
random()
- это функция, которая возвращает случайное число в [0.0, 1.0).
weight(x)
- это функция из [0.0, 1.0) в [0.0, 1.0), которая определяет требуемое поведение при взвешивании.
"r * n / watermark
" в качестве аргумента weight()
служит для нормализации диапазона аргументов. Возможно, эта нормализация не нужна для некоторых вариантов весовой функции.