Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
00464.docx
Скачиваний:
15
Добавлен:
13.11.2022
Размер:
1.65 Mб
Скачать

Стек отложенных заданий

Другой прием устранения рекурсии продемонстрируем на примере задачи о ханойских башнях.

Написать нерекурсивную программу для нахождения последовательности перемещений колец в задаче о ханойских башнях.

Решение. Вспомним рекурсивную программу, перекладывающую i верхних колец с m на n:

procedure move(i,m,n: integer);

| var s: integer;

begin

| if i = 1 then begin

| | writeln ('сделать ход ', m, '->', n);

| end else begin

| | s:=6-m-n; {s - третий стержень: сумма номеров равна 6}

| | move (i-1, m, s);

| | writeln ('сделать ход ', m, '->', n);

| | move (i-1, s, n);

| end;

end;

Видно, что задача "переложить i верхних дисков с m -го стержня на n -ый" сводится к трем задачам того же типа: двум задачам с i-1 дисками и к одной задаче с единственным диском. Занимаясь этими задачами, важно не позабыть, что еще осталось сделать.

Для этой цели заведем стек отложенных заданий, элементами которого будут тройки . Каждая такая тройка интерпретируется как заказ "переложить i верхних дисков с m -го стержня на n -ый". Заказы упорядочены в соответствии с требуемым порядком их выполнения: самый срочный - вершина стека. Получаем такую программу:

procedure move(i,m,n: integer);

begin

| сделать стек заказов пустым

| положить в стек тройку <i,m,n>

| {инвариант: осталось выполнить заказы в стеке}

| while стек непуст do begin

| | удалить верхний элемент, переложив его в <j,p,q>

| | if j = 1 then begin

| | | writeln ('сделать ход', p, '->', q);

| | end else begin

| | | s:=6-p-q;

| | | {s - третий стержень: сумма номеров равна 6}

| | | положить в стек тройки <j-1,s,q>, <1,p,q>, <j-1,p,s>

| | end;

| end;

end;

(Заметим, что первой в стек кладется тройка, которую надо выполнять последней.) Стек троек может быть реализован как три отдельных стека. (Кроме того, в паскале есть специальный тип, называемый "запись" ( record ), который может быть применен.)

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

Написать нерекурсивный вариант программы быстрой сортировки. Как обойтись стеком, глубина которого ограничена , где - число сортируемых элементов?

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

откуда очевидной индукцией получаем .

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]