Это может быть сложно, если вы не будете осторожны (т. Е. Используя алгоритм перетасовки naïve). Взгляните на Fisher-Yates/Knuth shuffle algorithm для правильного распределения значений.
Как только у вас есть алгоритм перетасовки, остальное должно быть легко.
Адрес more detail от Jeff Atwood.
Наконец, вот 1 implementation and description пользователя Jon Skeet.
EDIT
Я не верю, что есть решение, которое удовлетворяет ваши два противоречивых требований (первым, чтобы быть случайным, без повторов и секунд, чтобы не выделять какую-либо дополнительная памяти). Я считаю, что вы можете преждевременно оптимизировать свое решение, поскольку последствия для памяти должны быть незначительными, если только вы не встроены. Или, может быть, я просто недостаточно умен, чтобы придумать ответ.
Приведем здесь код, который создаст массив равномерно распределенных случайных индексов с использованием алгоритма Knuth-Fisher-Yates (с небольшой модификацией). Вы можете кэшировать полученный массив или выполнить любое количество оптимизаций в зависимости от остальной части вашей реализации.
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
до половины размера в памяти до тех пор, пока вы не более чем 65535 пунктов в списке воспроизведения. Вы всегда можете программно переключиться на int
, если размер превышает ushort.MaxValue
. Если бы я лично добавил в плейлист более 65 тыс. Элементов, я бы не был шокирован увеличением использования памяти.
Помните, что это управляемый язык. VM всегда резервирует больше памяти, чем вы используете, чтобы ограничить количество раз, когда нужно запросить ОС для большей ОЗУ и ограничить фрагментацию.
EDIT
Ладно, последняя попытка: мы можем смотреть настроить торговлю/производительность памяти от: Вы могли создать список целых чисел, а затем записать его на диск. Затем просто держите указатель на смещение в файле. Затем каждый раз, когда вам нужен новый номер, у вас просто есть дисковый ввод-вывод. Возможно, вы можете найти какой-то баланс здесь и просто прочитать N -размерные блоки данных в память, где N - это номер, с которым вам удобно.
Кажется, что много работы для алгоритма перетасовки, но если вы мертвы для сохранения памяти, то, по крайней мере, это вариант.
Смотрите также: http://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm –
без изменения исходного списка или выделения дополнительной памяти , вы не можете отслеживать повторы. Это приводит к меньшему, чем звездному опыту пользователя. –
полностью согласен с Mark Ransom –