Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Практика продвинутого программирования на Pascal _ Обсуждение темы "Как правильно перемешивать массивы"

Автор: IUnknown 3.08.2011 16:34

М
Обсуждение темы в FAQ, http://forum.pascal.net.ru/index.php?showtopic=28631

Тема в FAQ разделена. Предлагаю обсуждать здесь, после обсуждения дополнить или исправить тему в FAQ.



Не надо уводить от одной задачи, и приводить к другой...

Вот так, как ты написал в самом верхнем примере, не делается перемешивание. Так генерируются данные уже в перемешанном виде, правда? А то как ты показывешь ниже - это как раз перемешивание (т.е., ранее сгенерировал в прямой последовательности, а потом - перетусовал)... Есть 2 большие разницы между этими вещами. Не надо их сливать в одно, и уж тем более - нельзя сравнивать их быстродействие. Потому что я могу с легкостью сделать так:

for i := 1 to n do begin
repeat
candidat := random(n) + 1; // от 1 до n
can := container.exists(candidat);
until can;
container.push_back(candidat);
end;
, и все будет по-прежнему работать; независимо от того, насколько сложный объект содержится в контейнере, он будет инициализироваться целочисленным значением ОДИН раз, и не будет никаких копирований с места на место, которые могут запросто убить весь тот прирост производительности (если он даже и есть): тебе для того, чтобы поменять местами 2 элемента массива надо инициализировать временный элемент, потом произвести 3 операции копирования, потом временный элемент деинициализировать. Это может быть дольше, чем мой цикл
Кстати, (Показать/Скрыть)


Особенно актуально все вышесказанное становится в свете того, что ты сам заговорил о "сапёре" - ну вот решил я написать "сапёра" с использованием ООП (и не надо мне говорить что это неправильно - как хочу, так и пишу), а твой способ, как оказывается, просто не подходит для этого (если работать сразу с массивом объектов).

В крайнем случае - можно воспользоваться советом, и перемешать указанным образом вспомогательный индексный массив, а потом уже пройти по нему и в нужном порядке проинициализировать элементы рабочего массива объектов:
Вот так (Показать/Скрыть)

Автор: Lapp 5.08.2011 4:10

Каким-то образом я проглядел пост IUnknown, хотя заглядывал специально в обсуждаемую тему при написании того замечания об обсуждении (наверное, заглянул в таб, не обновив)). Приношу свои извинения и делаю этот своеборазный Up smile.gif.

Автор: TarasBer 29.08.2011 13:55

> Вот так, как ты написал в самом верхнем примере, не делается перемешивание. Так генерируются данные уже в перемешанном виде, правда? А то как ты показывешь ниже - это как раз перемешивание (т.е., ранее сгенерировал в прямой последовательности, а потом - перетусовал)...

Ну да, надо ещё массив скопировать туда или обратно, чтобы код был одинаков.
Ну не буду же я ещё и учить людей копировать массивы.

> независимо от того, насколько сложный объект содержится в контейнере, он будет инициализироваться целочисленным значением ОДИН раз, и не будет никаких копирований с места на место, которые могут запросто убить весь тот прирост производительности (если он даже и есть): тебе для того, чтобы поменять местами 2 элемента массива надо инициализировать временный элемент, потом произвести 3 операции копирования, потом временный элемент деинициализировать

Это уже оффтоп.
Во-первых, можно менять местами не сами объекты, а только нужное нам поле "есть ли бомба".
Во-вторых, проблему перемещения сложных объектов я тут пытался поднять, тему создал, но там не ответили ничего. Да, проблема есть, решают её хранением указателей со счётчиками ссылок, конструктором сдвига (в С++0х ввели, полезная вещь, в Аде будет в стандартном векторе?), но это всё уже выхоодит за рамки вопроса о перемешивании массива.

> Особенно актуально все вышесказанное становится в свете того, что ты сам заговорил о "сапёре" - ну вот решил я написать "сапёра" с использованием ООП (и не надо мне говорить что это неправильно - как хочу, так и пишу)

Неправильно обсуждать тут этот вопрос.

Короче, я скажу предысторию: я вбил в гугл "алгоритм перемешивания массива", попал (по первой ссылке!) на пхп-форум, где тело набило тот код, что я привёл, как плохой (только он работает за О(n*n*log(n)), так как проверка наличия в массиве делается там перебором, а в комментарии я написал про O(n*log(n)), но это для проверки через массив флагов), да ещё и написало что-то типа "это мля, я Кнута читал, ёпт, но там эта, как её, математика везде, ну его нах короче". Решил написать сюда, чтобы первая ссылка вела не туда.
А, та ссылка уже не первая, а вторая, хорошо.