Цитата(Lapp @ 9.10.2009 4:16)
Спасибо за вопрос, Clerick! Я как-то раньше не задумывался - плевал, пока не заплюю, с проверкой на повторы.. Но это же жутко неэффективно! Вот, задумался - результат тут...:
Есть такая статья, "Оптимизация – ваш злейший враг"
http://www.rsdn.ru/article/philosophy/Optimization.xmlТам речь немного о другом, но заголовок идеально подходит к данному случаю.
В любом случае, если уж мы хотим оптимизировать, то должны сперва разобраться, а где же у нас узкое место.
В даном случае, очевидно, наиболее ресурсоемкой операцией является получение очередного ПСЧ. Да и весь цикл повторяется столько раз, сколько ячеек в поле.
По всей видимости, данный алгоритм должен заменить тот, в котором "метки" случайно набрасываются в поле с проверкой, не занята ли она уже.
Оцеки показывают, что количество проходов цикла и, соответственно, количество обращений к ДПСЧ будет меньше именно в исходном варианте при проценте заполнения не превосходящем примерно 60-67% (точно считать лень), т.е. алгоритм, предлагаемый как более эффективный, на самом деле имеет существенно меньшую эффективность. По краней мере, в большинстве случаев, когда процент заполнения менее упомянутых 60-67%. Если же процент заполнения больше, то задачу можно "перевернуть" и выбрасывать при помощи ДПСЧ "непомеченные" ячейки.
Таким образом, исходный алгоритм в слегка откорректированном виде будет ВСЕГДА эфективнее предложенного.
Пойдем дальше.
Можно ведт придумать алгоритм, в котором вызовов ДПСЧ будет РОВНО столько, сколько нужно помеченных клеток - и ни одной больше.
Навскидку могу предложить следующий (правда, не проверял его на качество распределения):
Нужно пометить K клеток из N, K < N.
1. В массиве заполняем первые K клеток, а остальные N-K оставляем пустыми.
2. Проходим циклом по первым K клеткам, для каждой находим случайное число в интервале [1..N] и обмениваем содержимое текущей [i] ячейки и ячейки с номером, соответствубщим выпавшему ПСЧ (для определенности - массив нумеруется с 1).