Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика и ВТ Брукшир.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5.07 Mб
Скачать

7.4 Стеки

Одним из свойств списка, делающих связную структуру более привлекательной по сравнению с непрерывной, является простота добавления и удаления записей внутри списка. Вспомните, что в случае непрерывного списка для выполнения этой операции могло понадобиться смещение всего массива имен для заполнения или создания свободного места. Если же разрешить добавление и удаление только в начале и конце структуры, то использовать смежную структуру становится удобнее. Примером такой структуры является стек (stack), то есть список, в котором элементы добавляются и удаляются только на одном конце. Следствием такого ограничения является то, что последний добавленный элемент всегда будет удален первым — из-за этого стеки называют структурами LIFO (last-in, first-out, последним прибыл — первым убыл).

Тот конец стека, где добавляются и удаляются элементы, называется вершиной стека (top). Другой конец часто называют основанием стека (stack's base). Чтобы отразить тот факт, что доступ к стеку ограничен верхней записью, мы используем для обозначения операций добавления и удаления специальные термины. Процесс добавления объекта в стек называется проталкиванием (push), а процесс удаления — выталкиванием (pop). To есть запись проталкивается в стек или выталкивается из него.

7.4.1Откат

Классическое применение стека можно наблюдать, когда программный модуль запрашивает выполнение процедуры. Для выполнения этого запроса компьютер должен передать управление процедуре; затем, когда процедура выполнится, компьютеру необходимо вернуться к тому месту в программном модуле, откуда был сделан запрос. Таким образом, для осуществления передачи управления должен существовать механизм запоминания местоположения, куда управление будет затем возвращено.

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

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

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

Приведем другой пример. Предположим, что нам необходимо напечатать имена, собранные в связный список (описанный в разделе 7.2), в обратном порядке, то есть чтобы последнее имя напечаталось первым. Но вызывает трудность то, что получить доступ к именам можно, только пройдя по связной структуре. Следовательно, нам требуется способ хранения каждого полученного имени до тех пор, пока все следующие за ним имена не будут получены и напечатаны. Решить эту проблему можно, пройдя список от начала до конца, одновременно проталкивая найденные имена в стек. Когда мы достигнем конца списка, то начнем выталкивать имена из стека и печатать их (рис. 7.9). Процедура решения приведена на листинге 7.2.

Листинг 7.2. Процедура печати связного списка в обратном порядке с использованием вспомогательного стека

procedure ReversePrint (List)

CurrentPointer <- указатель головы списка List

while (CurrentPointer не NIL) do

(push (проталкивание) имени из элемента, на который указывает CurrentPointer. в стек:

Считывание указателя из элемента списка List, на который указывает CurrentPointer,

и присваивание этого значения CurrentPointer.) while (стек не пустой) do

(pop (выталкивание) имени из стека и печать.)