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

Глава 45

Очереди и стеки

Но для функции GetFromQue, выбирающей из очереди первый символ, контроль строки на пустоту необходим, иначе работа модели нарушится. Функция возвращает состояние очереди, бывшее до извлечения символа (TRUE, если очередь не была пуста). А сам извлекаемый символ возвращается через параметр arg, — это ссылка на символьную переменную. Вот, пожалуй, и вся премудрость. Испытайте эту программу. Добавьте операторы печати для наблюдения за очередями.

Скитания товарного вагона

Прежде, чем углубиться в стек, вникнем в работу железной дороги. Вы знаете, как железнодорожники доставляют товарный вагон из пункта «А» в пункт «Б»? «Очень просто, — скажете, — цепляют к составу и тащат!» Тогда взгляните на рис. 100.

2

1 У 3

4

Рис. 100 – Доставка вагонов между несколькими станциями

Здесь показаны пять железнодорожных станций, четыре из которых обозначены цифрами, а пятая — узловая станция — буквой «У». Предположим, что со станции «1» надо доставить несколько десятков вагонов на другие станции (по направлению стрелок). С этих станций тоже везут вагоны, но соответствующие стрелки я не показал. Тащить вагоны поодиночке разорительно! Поэтому их собирают в составы по нескольку десятков вагонов. Накопив такой состав на станции «1», железнодорожники доставляют его на узловую станцию; сюда же стекаются составы с других направлений. На узловой творится самое интересное,

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

Но это ещё присказка, — сказка впереди.

345

Глава 45

Очереди и стеки

Сортировочная горка

Итак, на узловых станциях формируют новые составы с тем, чтобы каждый вагон следовал далее в нужном направлении. Для сортировки устроены так называемые сортировочные горки. Горка — это слегка наклоненный участок пути; если отцепить от стоящего на нём состава вагон, последний покатится под горку. Но укатится недалеко, — под горкой устроено несколько тупиков. Тупик — это обычное состояние программиста, но здесь я говорю о других тупиках, железнодорожных. Это участки пути, ограниченные с одной стороны земляным валом. Уткнувшись в этот вал, вагон остановится. Горка соединяется с тупиками железнодорожными стрелками, переключая которые можно направить катящийся с горки вагон в тот или иной тупик (рис. 101).

Стрелки

Горка

Тупики

Рис. 101 – Схема сортировочной горки

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

Наша цель: смоделировать сортировочную горку, то есть создать программу, ведущую себя подобно такой горке. Вагоны заменим символами; следовательно, и состав и стоящие в тупиках вагоны мы представим строками. Будем считать первый символ строки первым вагоном состава, — он прицеплен к локомотиву. В тупике первым будет вагон, стоящий у земляного вала. Легко догадаться, что обрабатывать вагоны будем по принципу стека, поскольку сцепщику всегда доступен только последний вагон.

346

Глава 45

Очереди и стеки

Договорившись об этом, сформулируем задачу окончательно. Дана строка символов (состав), из которой надо сформировать три других. Вагоны, обозначенные большими буквами ’A’…’Z’, отправим на станцию «A»; другие, обозначенные маленькими буквами ’a’…’z’, — поедут к станции «B», а третьи, обозначенные цифрами ’0’…’9’, к станции «C». Программа должна сформировать три строки — это вновь собранные составы. Первый символ в них,

— это вагон, прицепленный непосредственно к локомотиву.

Для решения задачи надо всего лишь в точности повторить действия сцепщика и стрелочника. Будем «отцеплять» символы от строки и «заталкивать» их в стеки — это наши тупики. Значит, надо построить механизм для стеков. Он будет похож на механизм для очереди: элементы храним в строковых переменных, а для занесения и извлечения элементов из стека учредим две процедуры. По традиции программисты называют эти процедуры так: Push — затолкнуть в стек, и Pop — вытолкнуть из стека.

Процедура заталкивания в стек Push присоединяет символ к концу строки. Она точь-в-точь повторяет процедуру установки в очередь, только называется иначе.

А функция выталкивания из стека Pop возвращает последний символ строки, одновременно удаляя его оттуда. Если же стек окажется пуст, функция сообщит об этом. Сходство с функцией извлечения из очереди очевидно, разница лишь в позиции извлекаемого символа: для очереди это первый символ, а для стека — последний.

Теперь вам не составит труда разобраться в показанной ниже программе P_45_2. Обратите внимание на отцепку вагонов от исходного состава: она тоже выполняется функцией выталкивания Pop, поскольку исходный состав трактуется как непустой стек.

347

Глава 45

Очереди и стеки

{P_45_2 – Сортировочная станция }

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

procedure Push(var aStack: string; arg: char); begin

aStack:= aStack + arg; { добавляем в конец строки }

end;

{ Извлечение элемента из стека }

function Pop(var aStack: string; var arg: char): boolean; begin

if Length(aStack) = 0

{ если стек пуст }

then

Pop:= false

{ сообщаем об этом }

else

begin

 

 

{ возвращаем последний элемент }

 

arg:= aStack[Length(aStack)];

 

{ и удаляем его из стека }

 

Delete(aStack, Length(aStack), 1);

 

Pop:= true; { признак того, что стек не был пуст }

end;

end;

 

 

 

var S : string;

{ исходный состав }

SA, SB, SC : string;

{ три сортировочных тупика A,B,C}

c : char;

{ очередной вагон }

begin

 

 

S:= 'HEjd31kDJK62px912se3BKdwL9'; { Исходный состав }

Writeln('Исходный состав:

'+S);

SA:=’’; SB:=’’; SC:=’’;

{ очистка тупиков }

{Отцепляем вагоны от исходного состава и заталкиваем в тупики } while Pop(S, c) do begin

if c in ['A'..'Z'] then Push(SA, c); if c in ['a'..'z'] then Push(SB, c); if c in ['0'..'9'] then Push(SC, c);

end;

{Теперь исходный состав пуст, то есть S='' }

{Выкатываем вагоны из тупика A и цепляем к первому составу } while Pop(SA, c) do Push(S, c);

Writeln('На станцию A : '+S);

S:=''; { Освобождаем пути }

{ Выкатываем вагоны из тупика B и цепляем ко второму составу }

348

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