2010-03-03 18 views
10

Estoy tratando de llenar una matriz de 20 ints con números del 1-20 en secuencia al azar. aquí es mi código:llenando una matriz con número aleatorio

int lookup[20]={0}; 
int array[20]={0}; 
srand(time(NULL)); 
for(int i=0;i<20;++i){ 
    bool done=false; 
    while(!done){ 
     int n=rand()%20; 
     if(lookup[n]==0){ 
      array[i]=n; 
      lookup[n]=1; 
      done=true; 
     } 
    } 
} 

He creado una matriz de búsqueda para comprobar si el número aleatorio aún no se elige y se almacena en la matriz. Como puede ver, he creado 2 bucles, uno para recorrer una matriz y el otro para elegir el número aleatorio. En cada iteración de bucle while, el número puede reaparecer y causar otro bucle while. ¿Hay una manera más rápida de hacer esto?

+0

aplicar la etiqueta random-number-generator –

+0

Vea también: http://stackoverflow.com/questions/1218155/random-number-but-dont-repeat, http://stackoverflow.com/questions/1816534/random -playlist-algorithm, http://stackoverflow.com/questions/417831/what-is-the-best-way-of-randomly-re-arranging-a-list-of-items-in-c, http://stackoverflow.com/questions/813935/randomizing-elements-in-an-array – outis

Respuesta

19

Puede llenar la matriz en secuencia y luego mezclarla. Eso evitaría tener que hacer más de 20 generaciones de números aleatorios.

Fisher-Yates shuffle: se puede hacer en O (n) tiempo.

de Wikipedia:

implementado correctamente, el shuffle Fisher-Yates es imparcial, por lo que cada permutación es igualmente probable. La versión moderna del algoritmo también es bastante eficiente, requiriendo solo tiempo proporcional al número de elementos que se barajan y sin espacio de almacenamiento adicional.

+1

+1 de hecho! Knuth Shuffle. –

+0

Si usa C++ específicamente y no C, la sugerencia de graham.reeds para usar std: random_shuffle lo llevará a donde quiere ir sin el riesgo de cometer un error al implementar el algoritmo de mezcla. Si está utilizando C, entonces hay una implementación de código en la página de Wikipedia (y probablemente en otra parte en la web) que puede copiar. – sfg

+0

¡Sí! Estoy usando C++ para esto. std :: random_shuffle está listo, pero creo que voy a intentar implementar el algoritmo de mezcla. Gracias por la respuesta. – James

0

pondría los 20 números aleatorios en una matriz, y luego copiar a otra matriz de 20 elementos, ordenar una matriz, y para cada número en la matriz ordenada, encontrar el número correspondiente en la matriz sin clasificar, y poner el índice del género allí.

+0

es O (n * n) ¿verdad? –

9

que podría llenar una matriz con números del 1 al 20 y utilizar std::random_shuffle

nota que no es necesario un vector para el caso de una simple matriz va a hacer.
ejemplo:

#include <iostream> 
#include <algorithm> 

using namespace std; 

int main(void) 
{ 
     int array[] = { 0, 1, 2, 3, 4 }; 

     srand(unsigned(time(NULL))); 

     random_shuffle(array, array+5); 

     for(int i=0; i<5; i++) 
       cout << array[i] << endl; 

     return 0; 
} 
1

Existe la posibilidad en el código de un bucle de ejecución muy largo. Si estás dentro del ciclo while (! Done), no hay garantía de que termines alguna vez. Obviamente, con una matriz de 20 elementos esto no será un problema en la práctica, pero podría causar problemas si amplía esto a muchos miles de elementos.

Una solución más confiable sería llenar la matriz secuencialmente y luego mezclarla después.

+0

"no hay garantía de que termine alguna vez": el ciclo termina con la probabilidad 1 si la función de número aleatorio es lo suficientemente buena, pero tiene razón en que el tiempo de ejecución esperado es deficiente. En el caso en que la longitud de la matriz es mayor que RAND_MAX, obviamente tiene un problema, pero eso tiene que ver con la manera dudosa en que el código intenta obtener un número aleatorio de 0 .. N-1 con distribución uniforme. Un Fisher-Yates que hace 'rand()% N' también sería débil para grandes N. –

+0

Tienes razón, si escalo para decir 1 millón de elementos seguramente tendrá algunos problemas de rendimiento. – James

15
+0

¡Sí! Use un algoritmo estándar; Fisher-Yates es muy fácil equivocarse. –

+3

Siempre me he preguntado por qué se llama 'random_shuffle'. Tipo de implica que hay un 'nonrandom_shuffle'. –

+0

+1 para STL. las matrices también proporcionan Iteradores RA. No es necesario para std :: vector. – pmr

0

Si puede utilizar contenedores, que acababa de llenar un std :: set con los números del 1 al 20.

Luego se puede tirar un número aleatorio real de la unidad y la inserta en la matriz.

0

algo como esto?

int n = 20; //total element of array 
int random = 0, temp=0, start=1; 

for(int i=0; i < n; ++i,++start) 
{ 
    array[i] = start; 
} 

for(int i=0; i<n ; ++i) 
{ 
    random=rand()%(n-i)+i; 
    //swapping, you can make it as a function 
    temp = array[i]; 
    array[i] = array [random]; 
    array[random] = temp; 

} 
0

otra forma posible

int array[20]={0}; 
int values[20]; 
for(int i = 0; i < 20; i++) 
    values[i] = i; 
int left = 20; 
for(int i = 0; i < 20; i++) 
{ 
    int n = rand() % left; 
    array[i] = values[n]; 
    left--; 
    values[n] = values[left]; 
} 

PS llena de nombers 0-19 no de 1 a 20.Igual que el original Ejemplo de código

+0

no use 'rand()% left' - ver por ej. Http://members.cox.net/srice1/random/crandom.html – Christoph

0

de Fisher-Yates:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

void shuffle(int array[], size_t size) 
{ 
    if(size) while(--size) 
    { 
     size_t current = (size_t)(rand()/(1.0 + RAND_MAX) * (size + 1)); 
     int tmp = array[current]; 
     array[current] = array[size]; 
     array[size] = tmp; 
    } 
} 

int main(void) 
{ 
    srand((int)time(NULL)); 
    rand(); // throw away first value: necessary for some implementations 

    int array[] = { 1, 2, 3, 4, 5 }; 
    shuffle(array, sizeof array/sizeof *array); 

    size_t i = 0; 
    for(; i < sizeof array/sizeof *array; ++i) 
     printf("%i\n", array[i]); 

    return 0; 
} 
0

espero que ayudará a:

std::generate(array, array + sizeof(array)/sizeof(int), ::rand); 

continuación tienen código completo:

#include<algorithm> 
#include<cstdlib> 
#include<iostream> 
#include<iterator> 

int main() 
{ 
    int array[] = {1, 2, 3, 4}; 
    const unsigned SIZE = sizeof(array)/sizeof(int); 

    cout << "Array before: "; 
    std::copy(array, array+SIZE, std::ostream_iterator<int>(cout, ", ")); 

    std::generate(array, array+SIZE, ::rand); // answer for your question 

    cout << "\nArray arter: "; 
    std::copy(array, array+SIZE, std::ostream_iterator<int>(cout, ", ")); 
} 

Si desea tener números más pequeños que los que puedes hacer después de generar:

std::transform(array, array+SIZE, array, std::bind2nd(std::modulus<int>(), 255)); 
Cuestiones relacionadas