2016-07-01 2 views
-4

Скажем, у меня есть предварительно заданный набор S из m элементов. Я хотел бы создать случайную комбинацию n (уникальных) элементов, взятых из S.Программирование на С: Генерировать случайные n-комбинации из заданного набора?

Есть ли простой способ реализовать это в C? Я посмотрел на Ранд(), но, похоже, он не делал то, что я хочу.

(EDIT, чтобы добавить больше деталей)

Специфической проблемой является случайным образом выбирать п различных элементов из массива размером м. Мой первый инстинкт должен сделать это:

idx_array = []

INT IDX = рандов()% м

[если IDX не в idx_array, добавить к idx_array. В противном случае повторите выше строки. Повторяйте до тех пор, пока idx_array не будет иметь размер n]

Но это не похоже, что этот процесс действительно случайный. Я все еще новичок в C и на самом деле просто хочу знать, есть ли встроенная функция для этой цели.

Любая помощь приветствуется.

+0

Пожалуйста, покажите свое исследование до времени. Сначала прочитайте страницу [Ask]. –

+1

_ Есть слишком много возможных ответов, или хорошие ответы будут слишком длинными для этого формата. Пожалуйста, добавьте детали, чтобы сузить набор ответов или изолировать проблему, на которую можно ответить в нескольких параграфах. –

+0

'Но это не похоже, что этот процесс действительно случайный. Я все еще новичок в C и на самом деле просто хочу знать, есть ли встроенная функция для этой цели. «Нет, ни один компьютер не может генерировать истинное случайное число. Это псевдослучайно. – SnakeDoc

ответ

-1

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

+0

Как и в ответе, вы, по сути, говорите «есть ответ» ... Не могли бы вы разместить какой-то контент в ответ? – Myst

1

Вместо того чтобы генерировать число от 1 до n с возможностью дубликата, перетасуйте массив, а затем выбрать из первых n элементов:

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

// Randomly shuffle a array 
void shuffle (int * array, int n) { 
    int i, j, tmp; 

    for (i = n - 1; i > 0; i--) { 
    j = arc4random_uniform(i + 1); 
    tmp = array[j]; 
    array[j] = array[i]; 
    array[i] = tmp; 
    } 
} 


int main (int argc, char const *argv[]) 
{ 
    const int m = 5; 
    const int n = 3; 

    int s[m] = {10, 20, 30, 40, 50}; 

    // Make a copy of s before shuffling it 
    int t[m]; 
    for(size_t i = 0; i < m; i++) 
    { 
     t[i] = s[i]; 
    } 
    shuffle(t, m); 

    // Now, the first n elements of t is what you want 
    for(size_t i = 0; i < n; i++) 
    { 
     printf("%d ", t[i]); 
    } 

    return 0; 
} 

Кредит Roland Illig для функции перетасовки Fisher-Yate.

+0

Классический удар производительности ... Вы перетасовываете целый массив, чтобы получить образец ... если массив имеет 2 ГБ данных и вы отбираете 512 байтов, это довольно ужасно. – Myst

+0

Старая пословица: сначала сделайте ее работу, а затем сделайте ее быстрой. Алгоритм тасования работает в 'O (n)', который очень эффективен. Однако, если вы имеете дело с массивом такого размера, определенная необходимость в оптимизации. –

+0

Вы, очевидно, правы, и ваш подход к тасованию является классическим решением проблемы. Я думаю, что это то, чему они учат в школах по всему миру ... Но отчасти поэтому я должен был указать на проблемы с производительностью. Люди забывают использовать свое мнение при применении известных решений. Во всяком случае, в надежде, что вы укажете на предупреждение о производительности в ответ, я дам этому свой голос :) – Myst

Смежные вопросы