Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
109
Добавлен:
26.03.2016
Размер:
5 Мб
Скачать
☆

Глава 43 Сортировка по-взрослому

Наше новейшее открытие — быстрый, как ракета, двоичный поиск. Но работает он лишь в сортированном массиве. Так в чем вопрос? Разве сортировка «пузырьком» нам не покорилась? Увы! «Пузырек» насколько же нетороплив, насколько и прост. Много ли проку от быстрого поиска, если выигрыш времени съест сортировка? Так ускорим её!

«Фермерская» сортировка

Отчего так медленно «всплывают пузырьки»? Не оттого ли, что мы сравниваем и обмениваем соседние элементы? Уяснить тонкости сортировки нам поможет правдивая история из жизни двух друзей.

Некий фермер — левша по имени Лефт — удостоился чести поставлять арбузы к столу Его Величества. Желая превзойти конкурентов и сохранить за собой королевский заказ, Лефт решил отбирать из урожая самые крупные ягоды (арбуз — это ягода). Выложив арбузы в длинный ряд, Лефт занялся их сортировкой. Работая в одиночку, он применил единственный доступный ему способ — «пузырёк». После трёх дней мучительных сравнений и перестановок Лефт понял, что без помощника ему не обойтись.

Сортировать урожай следующего года он позвал своего соседа и приятеля по имени Райт. Вдвоём они стали работать новым, придуманным Лефтом способом. Лефт стал у первого арбуза, а его приятель Райт побежал в конец ряда. Оттуда Райт стал продвигаться навстречу Лефту, сравнивая арбузы с тем, у которого прохлаждался Лефт (арбузы взвесили заранее, а вес нацарапали на кожуре). Когда Райт находил арбуз легче того, у которого стоял Лефт, их меняли местами: друзья просто швыряли арбузы друг другу.

Наконец Райт вплотную подошел к Лефту, и тогда на месте, где стоял Лефт, оказался самый легкий арбуз. Лефт шагнул ко второму арбузу, а Райт снова побежал в конец ряда, и всё повторилось. По окончании второго цикла на втором месте в ряду, где стоял Лефт, очутился второй по величине арбуз. Теперь первые два арбуза были отсортированы, и Лефт соизволил шагнуть к третьему. К сумеркам, совершив N-1 таких циклов, друзья закончили работу. Лефт, свежий как огурчик, ступил, наконец, к последнему арбузу, недоумевая, отчего его приятель Райт едва волочит ноги?

316

Глава 43 Сортировка по-взрослому

Left

Right

Рис. 94 – Сортировка массива с встречным движением индексов

Пусть друзья отдыхают, а мы поразмыслим, много ли толку в изобретении Лефта? Поскольку при каждом обмене арбузы перемещались на большое расстояние, то возможно, что таких обменов потребовалось меньше, чем при «пузырьке». Пока это лишь догадка, которую предстоит проверить. А пока соорудим и испытаем процедуру сортировки, придуманную Лефтом, назовём её FarmSort — «фермерская» сортировка.

Программа с процедурой перед вами. Введите её и проверьте, действительно ли процедура Лефта сортирует массив, не ошибся ли фермер?

{ P_43_1 Программа для проверки «фермерской» cсортировки }

const

CSize=10;

{ размер массива }

type

TNumbers = array [1..CSize] of Integer; { тип для массива }

var

Arr : TNumbers;

{ сортируемый массив }

317

Глава 43 Сортировка по-взрослому

{Процедура «фермерской» сортировки } procedure FarmSort(var arg: TNumbers);

var L, R, T: Integer; begin

for L := 1 to CSize-1 do

{Сдвигаем правый индекс влево }

for R := CSize downto L+1 do begin

{ Если левый элемент оказался больше правого,

то меняем элементы местами } if arg[L] > arg[R] then begin

{ Перестановка элементов массива }

T:= arg[L]; arg[L]:= arg[R]; arg[R]:= T;

end;

end;

end;

{Процедура распечатки массива, arg – строка сообщения } procedure ShowArray(const arg: string);

var i: integer; begin

Writeln(arg);

for i:=1 to CSize do Writeln(Arr[i]); Readln;

end;

var i: integer; begin

{Заполняем массив случайными числами }

for i:=1 to CSize do Arr[i]:=1+Random(1000); ShowArray('До сортировки:');

FarmSort(Arr);

ShowArray('После сортировки:');

end.

Быстрая сортировка

«Здесь что-то не так, — стучало в голове Райта, пока он челноком мотался из конца в конец ряда, — почему я бегаю, а он стоит? Это несправедливо! К следующему урожаю я придумаю лучший способ сортировки!».

Через год Лефт опять позвал Райта на помощь.

Хорошо, — согласился Райт, — но теперь командовать буду я.

318

Глава 43 Сортировка по-взрослому

Пройдясь вдоль ряда, Райт прикинул на глазок вес среднего по величине арбуза. «Запомни этот вес, — сказал он Лефту, — и ступай к началу ряда», — а сам отправился в другой конец. «Теперь иди ко мне, пока не найдешь арбуз тяжелее указанного мною». Лефт так и сделал, — найдя первый такой арбуз, он остановился и крикнул об этом Райту. «Теперь моя очередь!» — отозвался Райт и стал двигаться навстречу Лефту, попутно отыскивая арбуз легче среднего. Дойдя до такого арбуза, Райт остановился и скомандовал: «Меняемся арбузами!», — и друзья швырнули арбузы друг другу.

— Снова твоя очередь! — крикнул Райт, — продолжай двигаться ко мне! — а сам присел отдохнуть.

Так поочередно друзья шли навстречу друг другу, время от времени обмениваясь арбузами. Где то в середине ряда они встретились.

—Ну и чем обернулась твоя идея со средним арбузом? — ядовито осведомился Лефт, — мы уже встретились, не отсортировав ни единого!

—Да, — согласился Райт, — зато любой арбуз на твоей левой половине ряда легче любого на моей правой половине.

—Откуда ты знаешь?

—Оттуда! Ведь все твои арбузы легче среднего, а все мои — тяжелее!

—Да, пожалуй, так, но что нам это даёт? — не унимался Лефт.

—А то, что теперь эти две половинки ряда можно сортировать отдельно. Смекнул? Нам меньше бегать придется, ведь расстояния вдвое короче!

—И как же мы будем сортировать эти половинки?

—Тем же порядком, но по очереди, — сначала твою половину, потом мою.

И Райт стал прикидывать средний вес арбузов в левой половине ряда. Этот средний вес был, разумеется, меньше того, что в первом случае. Переведя дух, друзья повторили те же действия с левой половиной ряда. В серединке этой половинки они встретились вновь.

— Видишь, как быстро мы сошлись, — отметил Райт, — а всё потому, что ряд стал вдвое короче. Теперь все арбузы в левой четвертинке легче тех, что в правой четвертинке. Продолжим действовать так же, и отсортируем четвертинки по отдельности.

И фермеры продолжили дележку ряда: первую четвертинку разбили на две осьмушки, первую осьмушку — на две шестнадцатых и так далее, пока кусочек ряда не съежился до одного-двух арбузов. Этот кусочек они отсортировали моментально и пружина стала раскручиваться в обратную сторону. В конце

319

Соседние файлы в папке delphi