Помогите с алгоритмом случайной выборки чисел из заданного массива

Тема в разделе "WASM.A&O", создана пользователем int2e, 25 янв 2009.

  1. int2e

    int2e New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2009
    Сообщения:
    169
    Привет воины
    Есть массив указателей unsigned integer AddrArray[100]

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

    Подскажите, как реализовать эффективнее всего?

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

    Но чую - это неправильно и можно как-то сделать красивее.
     
  2. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    xorshift?
     
  3. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    ставеть на место уже выбранного ноль...
    чтото типа
    Код (Text):
    1. for (i=0;i<n;i++)
    2.  x=0;
    3.  while (!viborka[i])
    4.  {
    5.    k=rand()%n;
    6.    viborka[i]=AddrArray[k];
    7.  }
    8.  AddrArray[k]=0;
    9. }
     
  4. int2e

    int2e New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2009
    Сообщения:
    169
    Freeman
    нннет.... Все-равно прийдется проверять на ноль...А если ноль - то повторно вызывать процедуру выборки.
    В нашем случае вызов rand() и сравнение. Теоретически, если ранд() будет возврашать одну и ту же величину либо всего 19 значений вместо 20 - вся система повиснет...
    Т.е. за подобную реализацию мне снимут балы.

    Нужно как-то проще...
    Например разбить массив на интервалы и брать элементы от каждого интервала...Или что-то подобное..
     
  5. int2e

    int2e New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2009
    Сообщения:
    169
    murder
    хоршифт - это, насколько я знаю, простой генератор случайных чисел.
     
  6. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    Можно наподобие как стандартный random_shuffle работает:
    Код (Text):
    1. for (int i=0; i<20; ++i) {
    2.    int j = i + rand() % (n-i);
    3.    swap (a[j], a[i]);
    4. }
    По окончании первые 20 элементов массива будут случайно выбранными 20 элементами из него.
     
  7. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    дополнительный код. для длины последовательности в >= 20 ф-я найдется сразу
     
  8. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    Тут в разделе статей по вирусологии есть какой-то особохитров..анный алгоритм обращения к рандомным элементам (там это используется для расшифровки тела из декриптора), псевдослучайные обращения каждый раз к разным элементам, пока не переберуться все. Имхо то что нужно....


    А вобще, это форум по низкоуровневому программированию, вопросы по СИ можно задать на форумах соответствующей тематики...
     
  9. int2e

    int2e New Member

    Публикаций:
    0
    Регистрация:
    9 янв 2009
    Сообщения:
    169
    1. Это форум СИСТЕМНОГО И низкоуровневого программирования
    2. Это раздел A&O
     
  10. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    тьфу ты. перепутал. циклический код.
    http://ru.wikipedia.org/wiki/%D0%A6%D0%B8%D0%BA%D0%BB%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BA%D0%BE%D0%B4
    все просто и ничего сложного.
     
  11. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    Для С есть отдельная ветка, A&O и другие ветки по умолчанию для ассемблера.
    В сортировках массива нет ничего системного и низкоуровневого...
     
  12. iamlamer

    iamlamer New Member

    Публикаций:
    0
    Регистрация:
    20 июн 2005
    Сообщения:
    273
    Адрес:
    Russia
    Элементарно. Юзай идею линейного конгруэнтного ДПСЧ:
    1) выбери С=100
    2) выбери A=8t+5, где t - целое число. Например: 13, 21 и т.п.
    3) выбери B= нечетное и не кратное 5 число (а можно и не выбирать).
    4) возьми какую-нить начальную затравку 0<R(0)<100.
    5) все остальные индексы получай как R(i)=(R(i-1)*A+B) mod C или просто R(i)=(R(i-1)*A) mod C.

    При этих условиях товарищ Кнут гарантирует 100 _неповторяющихся_ чисел в интервале от 0 до 99, что, сопсно гря, и нужно.
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    srand(GetTickCount());
    rand();
     
  14. roman_pro

    roman_pro New Member

    Публикаций:
    0
    Регистрация:
    9 фев 2007
    Сообщения:
    291
    Можно применить алгоритм, аналогично ловле льва в пустыне (разбиением на полупустыни/кусочки):

    0. Получаем границы отрезка start=0, end=100. Если start==end, то добавляем это число к результирующей выборке, инкрементируем счётчик count и дуем на проверку счётчика (в п.3). Иначе, если start<end переходим к п.1
    1. Генерируем случайное число (rnd) от 0 (start) до 100 (end), добавляем его к результирующей выборке, инкрементируем счётчик count.
    2. Число rnd фактически разбивает отрезок [start,end] на 2 интервала: [start, rnd) и [rnd, end]
    3. Для каждого из отрезков из п.2 поступаем аналогично как в п.1, пока либо счётчик не достигнет нужного значения 20, либо пока отрезки из п.2 не выродятся (т.е. start==end - начало и конец отрезка будут совпадать). Если чисел будет только 19, то алгоритм, выведет все 19 возможных чисел (в случайном порядке) и остановится (все отрезки выродятся в точки), зависания не будет.

    process [0, 100]:
    rnd[0,100]=37 => result={37} => process [0, 37) & process [37, 100]

    process [0, 37):
    rnd[0,37)=13 => result={37,13} => process [0, 13) & process [13, 37)

    process [37, 100]:
    rnd[37, 100]=69 => result={37,13,69} => process [37, 69) & process [69, 100]

    ну и т.д.
    Собственно, тут важен сам принцип, ибо в вышеописанном алгоритме могут быть косяки, но они решаемы. Главное, что выпадения одного и того же случайного числа дважды мы избегаем by design
     
  15. Spectrum

    Spectrum Member

    Публикаций:
    0
    Регистрация:
    8 дек 2005
    Сообщения:
    43
    Адрес:
    Одесса
    Более быстрым получался вариант "топания" к соседним элементам в массиве, чтобы не вызывать выборку заново. Вроде считаем, что если попал в выбранный, то попал просто рядом.
    А сравнение с выбранным - быстрее по меткам в параллельном массиве.