Esto realmente puede ser complicado si no tiene cuidado (es decir, usando un ingenuo algoritmo de mezcla aleatoria). Eche un vistazo a Fisher-Yates/Knuth shuffle algorithm para una distribución adecuada de los valores.
Una vez que tenga el algoritmo de mezcla, el resto debería ser fácil.
Aquí está more detail de Jeff Atwood.
Por último, aquí está el implementation and description de Jon Skeet.
EDITAR
No creo que hay una solución que satisfaga sus dos requisitos conflictivos (en primer lugar, a ser al azar, sin repeticiones y segundo para no asignar ninguna memoria adicional). Creo que es posible que optimice prematuramente su solución, ya que las implicaciones de memoria deberían ser insignificantes, a menos que esté incrustado. O, tal vez, no soy lo suficientemente inteligente como para encontrar una respuesta.
Con eso, aquí hay un código que creará una matriz de índices aleatorios distribuidos uniformemente utilizando el algoritmo Knuth-Fisher-Yates (con una ligera modificación). Puede almacenar en caché la matriz resultante o realizar cualquier cantidad de optimizaciones dependiendo del resto de su implementación.
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;
}
NOTA: Se puede utilizar en lugar de ushort
int
a la mitad del tamaño de la memoria, siempre y cuando usted no tiene más de 65.535 artículos en su lista de reproducción. Siempre puede cambiar de forma programática a int
si el tamaño excede ushort.MaxValue
. Si yo, personalmente, agregué más de 65 mil elementos a una lista de reproducción, no me sorprendería la mayor utilización de la memoria.
Recuerde, también, que este es un lenguaje administrado. La máquina virtual siempre reservará más memoria de la que está utilizando para limitar el número de veces que necesita pedirle al sistema operativo más RAM y limitar la fragmentación.
EDITAR
bien, último intento: podemos mirar para modificar el comercio de rendimiento de memoria/apagado: Usted podría crear su lista de enteros, a continuación, escribir en el disco. Luego solo mantenga un puntero al desplazamiento en el archivo. Luego, cada vez que necesite un número nuevo, solo tendrá que lidiar con las E/S de disco. Quizás usted puede encontrar un cierto equilibrio aquí, y acaba de leer N bloques -sized de datos en la memoria, donde N es un número que se sienta cómodo.
parece como un montón de trabajo para un algoritmo aleatorio, pero si estás muerto-set en la conservación de la memoria, entonces por lo menos es una opción.
Consulte también: http://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm –
Sin modificar la lista original o la asignación de memoria adicional , no puedes rastrear repeticiones. Esto resulta en una experiencia de usuario menos que estelar. –
totalmente de acuerdo con Mark Ransom –