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

Глава 45 Очереди и стеки

Хорошей вещи найдется уйма применений. Взять хотя бы строки, из которых мы построим сейчас инструменты системных программистов — очереди и стеки.

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

Вовочка в потоке событий

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

Смотрите: вот компьютер и Вовочка, мирно играющий в «звездные войны». Входит мама: «Вова, ты уроки сделал?». Вова неохотно откладывает игру и приступает к урокам. Через полчаса мама снова беспокоит его: «Вовочка, я не могу отойти от плиты. Сгоняй-ка быстро за луком». Уроки откладываются, и Вова отправляется в магазин. По пути он видит гоняющих мяч приятелей, — им не хватает вратаря. Как не помочь друзьям? Поход в магазин откладывается, и Вовочка на страже ворот. Делу время, а потехе час. Закончилась игра, и можно выполнить мамино поручение. Купив луку, Вова доделывает отложенные уроки и возвращается к первому занятию — «звездным войнам».

Вовочка обрабатывал события по принципу стека, — скажет об этом системный программист. Другое название стека — дисциплина обслуживания LIFO, что значит «Last-In, First-Out», или по-русски: «последним пришел — первым ушел». Мы соприкоснулись со стеком, разбирая рекурсивную процедуру быстрой сортировки. Помните пример с укладкой рюкзака? А вот ещё пример: магазин для патронов. Патрон, вставленный в магазин последним, выстрелит первым, и наоборот.

Итак, пример с Вовочкой показал, что важные события мы обслуживаем по принципу стека.

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

340

Глава 45

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

Или другой пример — печатание документов на сетевом принтере. Когда принтер занят, операционная система ставит запросы на печать в очередь. А затем

— по мере готовности принтера — выбирает файлы из этой очереди и отправляет принтеру.

За очередью тоже закрепилось свое сокращение — FIFO, что значит «First-In, First-Out» — «первым пришел, первым ушел». В отличие от стека, в

очередь попадают маловажные события.

Обратите внимание, что элементами очередей и стеков может быть что угодно: события, предметы и даже люди. Рассмотрим два примера: запись в танцевальный кружок и сортировочную горку.

Танцевальный кружок

В городе набирали детей в кружок бального танца. Запись в кружок вела преподающая в нём дама. Приходящих мальчишек и девчонок она стремилась объединять в пары при первой возможности с тем, чтобы они сразу приступали к занятиям. Однако на запись дети приходили поодиночке в разное время и в случайном порядке, — то несколько мальчиков подряд, то несколько девочек. Дама не слыхала о системном программировании, а потому прибегла к здравому смыслу. Взяв пару записных книжек, она поступала так.

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

Пусть наша новая программа повторит действия танцевального тренера, — инженеры называют это моделированием. Работать будем, конечно, не с живыми детьми, мы представим их как-то иначе. Условимся обозначать их латинскими буквами: девочек — строчными, а мальчиков — заглавными (только потому, что они выше ростом).

Входной поток

Выходной поток

Рис. 99 – Запись в танцевальный кружок

341

Глава 45

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

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

ZHJKqwertASDyuiopQWERTYUIOPasdf

означает, что первым явится мальчик по имени Z, а последней — девочка по имени f. Первая пара составится из мальчика Z и девочки q. Это упрощение не меняет сути нашей модели, но избавляет её от второстепенных деталей.

Итак, с учетом всех договоренностей, явим задачу в окончательном виде. Дана строка, состоящая из заглавных и строчных букв латинского алфавита — «мальчиков» и «девочек». Мы должны сформировать другую строку, состоящую из тех же символов, но следующих попарно: сначала заглавная буква — «мальчик», затем строчная — «девочка». Пары разделяются пробелом. Например, для указанной выше строки, пары должны быть составлены так.

Zq Hw Je Kr At Sy Du Qi Wo Ep Ra Ts Yd Uf

А напоследок программа должна напечатать имена тех, кто временно остался без пары. Здесь это будут пришедшие в числе последних мальчики I, O и P.

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

Сделаем так. Элементы очереди — символы — будем хранить в строковых переменных. К ним добавим ещё две процедуры: одну — для установки элемента в очередь, другую (это будет функция) — для извлечения из очереди первого элемента. Назовем их соответственно PutInQue — «поставить в очередь» и GetFromQue — «извлечь из очереди» (Queue — «очередь» или «хвост»). Всё это представлено в программе P_45_1.

342

Глава 45

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

{P_45_1 - Запись в танцевальный кружок }

{Постановка символа arg в очередь Que }

procedure PutInQue(var Que: string; arg: char); begin

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

{ Выбор из очереди Que элемента в параметр arg }

function GetFromQue(var Que: string; var arg: char): boolean; begin

if Length(Que) = 0

{ если очередь пуста }

then GetFromQue:= false

 

else begin

 

GetFromQue:= true;

{ если не пуста }

arg:= Que[1];

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

Delete (Que, 1, 1);

{ и удаляем его из очереди }

end

 

end;

 

{ Глобальные переменные }

var S_IN : string;

{ входной поток – символы }

S_OUT : string;

{ выходной поток (пары) }

Boys : string;

{ очередь мальчиков }

Girls : string;

{ очередь девочек }

c1,c2 : char;

{ очередная пара – символы строки }

i : integer;

{ индекс во входном потоке }

begin {--- Главная программа ---}

{ задаем (вводим) входной поток: A..Z – мальчики, a..z – девочки } S_IN:='ZHJKqwertASDyuiopQWERTYUIOPasdf';

S_OUT:='';

{

выходной поток пока пуст }

Boys:='';

Girls:=''; {

Очищаем очереди мальчиков и девочек }

343

Глава 45

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

{ Цикл обработки входного потока } for i:=1 to Length(S_IN) do begin

c1:= S_IN[i]; { выбираем из входного потока } if c1 in ['A'..'Z']

then begin { если это мальчик...}

{ если в очереди есть девочка } if GetFromQue(Girls, c2)

{добавляем пару в выходной поток } then S_OUT:= S_OUT+c1+c2+’ ’

{а иначе помещаем мальчика в очередь } else PutInQue(Boys, c1);

end

else begin { а если это девочка...} { если в очереди есть мальчик } if GetFromQue(Boys, c2)

{добавляем пару в выходной поток } then S_OUT:= S_OUT+c2+c1+’ ’

{а иначе помещаем девочку в очередь } else PutInQue(Girls, c1);

end

end;

Writeln('Входной поток:' );

Writeln(S_IN);

Writeln('Выходной поток:' );

Writeln(S_OUT);

if Length(Boys)>0 then begin

Writeln('В очереди мальчиков остались:' );

Writeln(Boys);

end;

if Length(Girls)>0 then begin

Writeln('В очереди девочек остались:' );

Writeln(Girls);

end;

Readln;

end.

Процедура PutInQue просто добавляет символ в конец строки. Строго говоря, если длина строки достигнет 255, то новый символ не попадет в очередь. Но мы не станем усложнять программу дополнительными проверками, — считаем, что емкости очереди нам достаточно.

344

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