На самом деле это может быть сложно, если вы не будете осторожны (то есть, используя наивный алгоритм перетасовки). Взгляните на алгоритм Фишера-Йейтса / Кнута shuffle для правильного распределения значений.
Если у вас есть алгоритм тасования, все остальное должно быть легко.
Вот подробнее от Джеффа Этвуда.
Наконец, вот реализация и описание Джона Скита .
EDIT
Я не верю, что есть решение, которое удовлетворяет вашим двум противоречивым требованиям (во-первых, чтобы быть случайным без повторов, а во-вторых, чтобы не выделять дополнительную память). Я полагаю, что вы, возможно, преждевременно оптимизируете свое решение, поскольку последствия для памяти должны быть незначительными, если вы не встроены. Или, может быть, я просто недостаточно умен, чтобы придумать ответ.
С этим вот код, который создаст массив равномерно распределенных случайных индексов, используя алгоритм Кнута-Фишера-Йейтса (с небольшой модификацией). Вы можете кэшировать полученный массив или выполнить любое количество оптимизаций в зависимости от остальной части вашей реализации.
private static int[] BuildShuffledIndexArray( int size ) {
int[] array = new int[size];
Random rand = new Random();
for ( int currentIndex = array.Length - 1; currentIndex > 0; currentIndex-- ) {
int nextIndex = rand.Next( currentIndex + 1 );
Swap( array, currentIndex, nextIndex );
}
return array;
}
private static void Swap( IList<int> array, int firstIndex, int secondIndex ) {
if ( array[firstIndex] == 0 ) {
array[firstIndex] = firstIndex;
}
if ( array[secondIndex] == 0 ) {
array[secondIndex] = secondIndex;
}
int temp = array[secondIndex];
array[secondIndex] = array[firstIndex];
array[firstIndex] = temp;
}
ПРИМЕЧАНИЕ : Вы можете использовать ushort
вместо int
до половины размера памяти, если в вашем плейлисте не более 65 535 элементов. Вы всегда можете программно переключиться на int
, если размер превышает ushort.MaxValue
. Если бы я лично добавил в список воспроизведения более 65 тыс. Элементов, я бы не был шокирован увеличением использования памяти.
Помните, что это управляемый язык. Виртуальная машина всегда резервирует больше памяти, чем вы используете, чтобы ограничить число раз, когда ей нужно запрашивать у ОС больше оперативной памяти, а также ограничивать фрагментацию.
EDIT
Хорошо, последняя попытка: мы можем настроить баланс между производительностью и памятью: вы могли бы создать свой список целых чисел, а затем записать его на диск. Затем просто сохраните указатель на смещение в файле. Затем каждый раз, когда вам нужен новый номер, у вас просто есть дисковый ввод / вывод, чтобы иметь дело с. Возможно, вы можете найти какой-то баланс здесь и просто читать N блоков данных в память, где N - это число, с которым вам удобно.
Похоже, много работы для алгоритма случайного перемешивания, но если у вас нет шансов на сохранение памяти, то, по крайней мере, это вариант.