заполнение массива случайным числом

Я пытаюсь заполнить массив из 20 целых чисел с цифрами от 1 до 20 в случайном порядке. вот мой код:

 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;
      }
    }
 }

Я создал массив поиска, чтобы проверить, не выбрано ли случайное число, и сохранил его в массиве. Как вы можете видеть, я создал 2 цикла, один для обхода массива и время для выбора случайного числа. В каждой итерации цикла while число может появиться и вызвать другой цикл while. Есть ли более быстрый способ сделать это?

10 ответов


вы можете заполнить массив последовательно, а затем перетасовать его. Это предотвратило бы необходимость когда-либо делать более 20 поколений случайных чисел.

Фишер-Йейтс перемешать: можно сделать в o (n) времени.

из Википедии:

правильно реализовано, перетасовка Фишера-Йейтса беспристрастна, так что каждая перестановка одинаково вероятна. Современная версия алгоритма также достаточно эффективна, требуя только времени, пропорционального количество перетасовываемых предметов и отсутствие дополнительного места для хранения.


посмотреть std::random_shuffle и std::vector.


вы можете заполнить массив числами от 1 до 20 и использовать std:: random_shuffle

обратите внимание, что вам не нужен вектор, если на то пошло, простой массив будет делать.
пример :

#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;
}

в вашем коде есть возможность очень длинного цикла работы. Если вы внутри в то время(!готово) цикл нет никакой гарантии, что вы когда-нибудь закончите. Очевидно, что с массивом из 20 элементов это на практике не будет проблемой, но это может вызвать проблемы, если вы масштабируете это до многих тысяч элементов.

более надежным решением было бы заполнить массив последовательно и перемешайте ее после этого.


Я бы поместил 20 случайных чисел в массив, затем скопируйте в другой массив 20 элементов, отсортируйте один массив и для каждого числа в отсортированном массиве найдите соответствующее число в несортированном массиве и поместите индекс сортировки там.


Если вы можете использовать контейнеры, я бы просто заполнить std:: set с номерами от 1 до 20.

затем вы можете вытащить случайное число из набора и вставить его в массив.


другой возможный способ

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 заполняется номерами от 0 до 19 не от 1 до 20. Так же, как оригинал


пример кода для 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;
}

надеюсь, это поможет:

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

ниже у вас есть полный код:

#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, ", "));
}

Если вы хотите иметь меньшие числа, чем это, вы можете сделать это после генерации:

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

что-то вроде этого?

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; 

}