Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
algoritmy.docx
Скачиваний:
15
Добавлен:
27.09.2019
Размер:
237.74 Кб
Скачать

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

Структура данных 'стек'.

Стеком будем называть последовательность элементов, упорядоченных по времени их поступления. Эта последовательность доступна только с одного конца (вершины стека). Для работы со стеком необходим указатель вершины стека. Основные операции над стеком следующие: "запомнить в стеке" и "извлечь из стека" (причем извлекается последний из занесенных в стек элементов - то есть элемент с вершины стека). Поэтому говорят, что стек -- это структура типа LIFO - "Last In - First Out" - "последним зашел - первым вышел". Для представления стека в программе обычно используется одномерный массив (назовем его B), нумерация элементов которого начинается с нуля. В этом нулевом элементе массива хранится индекс первого свободного места в массиве (т.е. увеличенный на 1 индекс вершины стека). Если массив пуст, то указатель равен 1 (B[0]=1).

Добавление элемента X в стек реализуется очень просто - на первое свободное место (индекс которого хранится в B[0]) помещается X, после чего индекс первого свободного места увеличивается на 1:

B[B[0]]:=x; { Занести в стек } B[0]:=B[0]+1; { Увеличить указатель }

Если необходимо извлечь элемент x из стека, то берется последний из занесенных элементов (естественно, только в том случае, если стек непуст), и указатель на первое свободное место уменьшается на 1:

if B[0]<>1 { Если стек не пуст } then begin x:=B[B[0]]; { Взять элемент } B[0]:=B[0]-1; { Уменьшить указатель } end;

Статическая реализация стека на основе массива

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

При занесении элемента в стек элемент записывается на место, определяемое указателем стека, затем указатель модифицируется таким образом, чтобы он указывал на следующий свободный элемент (если указатель указывает на последний записанный элемент, то сначала модифицируется указатель, а затем производится запись элемента). Модификация указателя состоит в прибавлении к нему или в вычитании из него единицы (помните, что наш стек растет в сторону увеличения адресов.

Операция исключения элемента состоит в модификации указателя стека (в направлении, обратном модификации при включении) и выборке значения, на которое указывает указатель стека. После выборки слот, в котором размещался выбранный элемент, считается свободным.

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

Определение размера стека сводится к вычислению разности указателей: указателя стека и адреса начала области.

Программный модуль, представленный в примере, иллюстрирует операции над стеком, расширяющимся в сторону уменьшения адресов. Указатель стека всегда указывает на первый свободный элемент.

Предполагается, что в модуле будут уточнены определения предельного размера структуры и типа данных для элемента структуры:

const SIZE = ...;

type data = ...;

{==== Программный пример ====}

{ Стек }

unit Stack;

Interface

const SIZE=...; { предельный размер стека }

type data = ...; { эл-ты могут иметь любой тип }

Procedure StackInit;

Procedure StackClr;

Function StackPush(a : data) : boolean;

Function StackPop(Var a : data) : boolean;

Function StackSize : integer;

Implementation

Var StA : array[1..SIZE] of data; { Стек - данные }

{ Указатель на вершину стека, работает на префиксное вычитание }

top : integer;

Procedure StackInit; {** инициализация - на начало }

begin top:=SIZE; end; {** очистка = инициализация }

Procedure StackClr;

begin top:=SIZE; end;

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

Function StackPush(a: data) : boolean;

begin

if top=0 then StackPush:=false

else begin { занесение, затем - увеличение указателя }

StA[top]:=a; top:=top-1; StackPush:=true;

end; end; { StackPush }

{ ** выборка элемента из стека }

Function StackPop(var a: data) : boolean;

begin

if top=SIZE then StackPop:=false

else begin { указатель увеличивается, затем - выборка }

top:=top+1; a:=StA[top]; StackPop:=true;

end; end; { StackPop }

Function StackSize : integer; {** определение размера }

begin StackSize:=SIZE-top; end;

END.

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