Читаем Песни о Паскале полностью

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('До сортировки:');

      QuickSort(Arr, 1, CSize);

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

end.


Взгляните на параметры процедуры QuickSort. Вместе со ссылкой на массив, в процедуру передаются левая (aL) и правая (aR) границы сортируемой части массива (индексы). В процедуре вычисляется вес среднего арбуза по выбранной нами формуле и организуется поочередное встречное движение левого и правого индексов.

Самое интересное происходит после «встречи» индексов, когда массив разбит на две части. Удивительно, что теперь снова дважды вызывается та же самая процедура QuickSort: сначала для левой части массива, а затем – для правой (эти операторы выделены курсивом). Вспомните, – точно так же поступали и фермеры при сортировке арбузов.

«Так там фермеры, а здесь Паскаль! Позволено ль процедуре вызывать саму себя?» – слышу недоверчивый вопрос. Мы свыклись с тем, что из одной процедуры вызывают другую, из второй, – третью и так далее. Но чтобы саму себя? Это ж змея, глотающая свой хвост! Не оттого ли запутался фермер Лефт?

О рекурсии и стеке

Такой самовызов процедур называют рекурсией. «У попа была собака…» – помните? Это рекурсия, познакомимся с нею ближе (с рекурсией, а не собакой).

Легко заметить, что повторные вызовы процедуры QuickSort выполняются с другими значениями левой и правой границ. Чем глубже вызов, тем уже эти границы. С некоторого момента условия (R > aL) и (L < aR) перестают выполняться, и происходит выход из процедуры, – здесь фермеры возвращаются к несортированным частям массива. Таким образом, при выходе мы снова попадаем в эту же процедуру, но в другое место – следующее за вызовом. Окончательный выход из процедуры в главную программу случится только по завершении сортировки всего массива!

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

Разгадка в том, что при каждом входе в процедуру для её параметров и локальных переменных выделяется новый участок памяти. Теперь это будут уже другие параметры и локальные переменные, но с прежними названиями. Однако предыдущие их значения не теряются, а сохраняются в памяти, называемой стеком (Stack).

Что такое стек и как он работает? Случалось ли вам паковать рюкзак или глубокую сумку? Тогда вы знакомы со стеком. Все, что уложено в рюкзак, будет извлекаться из него в обратном порядке. Так же устроен и стек: при каждом вызове процедуры память для параметров и локальных переменных выделяется на его вершине. Эти новые значения временно закрывают предыдущие значения параметров, и так происходит при каждом входе в процедуру.

При выходе из неё последние значения параметров и локальных переменных удаляются с вершины стека, и тогда вновь открываются ранее скрытые. Так процедура «вспоминает» о неоконченной работе, и продолжает действия с параметрами, сохраненными в стеке ранее. В некоторый момент стек пустеет (когда все вещи из рюкзака вынуты), и тогда происходит окончательный выход из процедуры в главную программу.

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

Но стоп! О стеке поговорим позже, а сейчас займемся делом. Введите программу «P_43_2» и убедитесь в её правильной работе.

Алгоритмы, на старт!

Теперь в нашем распоряжении есть три процедуры сортировки, не устроить ли состязание между ними? На старт вызываются:

• BubbleSort – «пузырьковая» сортировка,

• FarmSort – «фермерская» сортировка,

• QuickSort – быстрая сортировка.

Время «спортсменов» мы будем засекать не по часам. И вы знаете, почему: мы сравниваем алгоритмы, а не компьютеры. В 42-й главе, где сравнивались алгоритмы поиска, мы оценивали время по количеству выполненных шагов. Поступим и здесь похожим образом. Вспомним, в чем состоит сортировка? – в сравнениях и перестановках. И много-много раз… Значит, трудоемкость сортировки можно оценить количеством этих двух операций – сравнений и перестановок, надо их только посчитать.

Перейти на страницу:

Похожие книги

Сломанная кукла (СИ)
Сломанная кукла (СИ)

- Не отдавай меня им. Пожалуйста! - умоляю шепотом. Взгляд у него... Волчий! На лице шрам, щетина. Он пугает меня. Но лучше пусть будет он, чем вернуться туда, откуда я с таким трудом убежала! Она - девочка в бегах, нуждающаяся в помощи. Он - бывший спецназовец с посттравматическим. Сможет ли она довериться? Поможет ли он или вернет в руки тех, от кого она бежала? Остросюжетка Героиня в беде, девочка тонкая, но упёртая и со стержнем. Поломанная, но новая конструкция вполне функциональна. Герой - брутальный, суровый, слегка отмороженный. Оба с нелегким прошлым. А еще у нас будет маньяк, гендерная интрига для героя, марш-бросок, мужской коллектив, волкособ с дурным характером, балет, секс и жестокие сцены. Коммы временно закрыты из-за спойлеров:)

Лилиана Лаврова , Янка Рам

Современные любовные романы / Самиздат, сетевая литература / Романы