Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры и алгоритмы обработки данных.doc
Скачиваний:
348
Добавлен:
12.03.2015
Размер:
1.81 Mб
Скачать

{Ссылочный тип для адресации элементов стека}

TStackItem = record

{базовый тип, определяющий структуру элементов стека}

inf : integer; {информационная часть}

next : pStackItem;

{ссылочная часть: поле для адреса следующего элемента}

end;

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

var sp : pStackItem;

Тогда конструкция sp^.inf будет представлять саму информационную часть, а конструкция sp^.next - адрес предыдущего элемента, который был помещен в стек непосредственно перед текущим.

Кроме того, для прохода по стеку от вершинного элемента к самому первому элементу необходима вспомогательная ссылочная переменная (например – с именем pCurrent). Она на каждом шаге прохода по стеку должна определять адрес текущего элемента. В самом начале прохода надо установить значение pCurrent = sp, а затем циклически менять его на значение pCurrent^.next до тех пор, пока не будет достигнут первый элемент стека. Очевидно, что для прохода надо использовать цикл с неизвестным числом повторений, а признаком его завершения должно быть получение в поле pCurrent^.next пустой ссылки nil. Отсюда следует, что ссылочное поле самого первого элемента стека должно содержать значение nil.

Тогда схематично проход по стеку можно представить следующим образом:

эл-т 1

nil

эл-т 2

next : 1

эл-т 3

next : 2

эл-т 4

next : 3

эл-т 5

next : 4

sp : вершина стека

Последовательные изменения указателя pCurrent

pCurrent : = sp; {начинаем проход с вершины стека}

While pCurrent <> nil do

begin

  1. Writeln ( pCurrent ^. Inf ); {вывод инф. части текущего элемента}

pCurrent : = pCurrent^.next; {переход к следующему элементу}

end;

Как выполняется добавление нового элемента в вершину стека?

Необходимые шаги:

  • выделить память для размещения нового элемента с помощью вспомогательной ссылочной переменной pTemp и стандартной программы new(pTemp); адрес этой области памяти сохраняется как значение переменной pTemp

  • заполнить информационную часть нового элемента (например: ReadLn(pTemp^.inf))

  • установить адресную часть нового элемента таким образом, чтобы она определяла адрес бывшего вершинного элемента: pTemp^.next : = sp;

  • изменить адрес вершины стека так, чтобы он определял в качестве вершины новый элемент: sp : = pTemp;

В этой последовательности шагов важен их порядок. Перестановка шагов 3 и 4 приведет к неправильной работе алгоритма вставки, т.к. на шаге 4 происходит изменение указателя sp, который перед этим на шаге 3 используется для установки правильного адреса в ссылочной части нового элемента.

эл-т 1

nil

эл-т 2

next

эл-т 3

next

новый эл-т

pTemp^.next : = sp

pTemp

sp

Как выполняется удаление элемента с вершины стека?

Необходимые шаги:

  • с помощью вспомогательной переменной рTempадресуем удаляемый элемент:

рTemp:=sp;

  • изменяем значение переменной spна адрес новой вершины стека:

sp : = sp^.next;

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

эл-т 1

nil

эл-т 2

next

эл-т 3

next

эл-т 4

next

sp

pTemp

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