Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник.docx
Скачиваний:
36
Добавлен:
21.12.2018
Размер:
2.15 Mб
Скачать

Процедуры, обслуживающие стек

Задача:

Создать процедуры для добавления элемента в стек (add), удаления элемента из стека (del), вывода содержимого стека на экран (wstack).

Описание переменных:

top – указатель на конец стека;

p – указатель на обслуживаемую в текущий момент область памяти.

Алгоритм решения задачи:

В теле основной ветки программы переменной top присваивается значение nil, т.е. стек еще не заполнен.

Добавление элемента в стек

Процедура add принимает в качестве фактического параметра число x, которое будет записано в содержательную часть элемента стека.

Выделяется память под указатель p, в содержательную часть которого записывается x, а в указатель – адрес, хранимый в top. Переменная top, в свою очередь, начинает ссылаться на выделенную под p область памяти.

Удаление элемента из стека

В процедуре del в переменную p записывается адрес предпоследнего элемента стека. Последний элемент, ссылка на который хранится в top, удаляется. Далее top присваивается адрес элемента, на участок памяти, который указан p. К этому времени он стал уже не предпоследним, а последним элементом.

Удаление не происходит, если стек пустой (top указывает на nil).

Вывод стека на экран

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

Программа на языке Паскаль:

type

pitem = ^item;

item = record

data: integer;

prev: pitem

end;

var

top, p: pitem;

n, k: integer;

procedure add(x:integer);

begin

new(p);

p^.data := x;

p^.prev := top;

top := p

end;

procedure del;

begin

if top<>nil then begin

p := top^.prev;

dispose(top);

top := p

end;

end;

procedure wstack;

begin

writeln('Содержимое стека: ');

p := top;

while p <> nil do begin

write(p^.data, ' ');

p := p^.prev;

end;

writeln;

end;

begin

top := nil;

for k := 1 to 10 do

add(k);

wstack;

writeln('Введите добавляемое в стек значение: ');

readln(n);

add(n);

wstack;

writeln('Количество элементов стека для удаления? ');

readln(n);

for k:=1 to n do

del;

wstack;

readln

end.

Примечания:

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

Вставка динамической переменной

Задача:

Построить цепочку динамическую структуру (стек), содержащую целые числа.

Затем между 4-й и 5-й динамической переменной вставить еще одну.

Описание переменных:

ir – указатель на конец структуры;

ip – указатель на текущую резервируемую память;

insert4 – указатель на 4-ю переменную стека;

insert5 – указатель на 5-ю переменную стека;

inserti – указатель на динамическую переменную, вставляемую между 4-м и 5-м элементами стека;

k – счетчик;

l – записываемое или считываемое из стека число.

Алгоритм решения задачи:

Сначала ir присваивается nil, т.е. указатель не указывает ни на какой участок памяти.

В цикле for происходит заполнение стека по следующему алгоритму. У пользователя запрашивается число, которое записывается в обычную переменную l. Резервируется участок памяти под указатель ip. В захваченный участок памяти записывается значение l и значение указателя ir (первый раз ir указывает на nil). Т.е. теперь ip указывает на nil. Переменная ir, в свою очередь, связывается с участком памяти, в который сейчас производилась запись. В итоге, после первой итерации получается структура, где первый элемент имеет указатель на nil, а переменная ir указывает на этот элемент. По окончании работы цикла for получается линейная динамическая структура данных стекового типа, где первый элемент указывает на nil, а последний элемент помечен (указан) переменной ir.

В цикле for помимо прочего, происходит связывание указателей insert4 и insert5 с четвертым и пятым элементами структуры соответственно. Когда происходит пятая итерация цикла (k = 5), то указатель-переменная ip хранит адрес пятого элемента, поэтому ее значение присваивается insert5. В следующей итерации цикла ip изменится, а в указателе insert5 сохранится адрес пятого элемента. В пятом элементе хранится адрес на четвертый элемент, который записывается в переменную insert4.

Вставка нового элемента структуры между 4-й и 5-й динамическими переменными происходит так. У пользователя запрашивается число, которое записывается в переменную l. Резервируется участок памяти, адрес которого помещается в указатель inserti. В содержательную часть этой области записывается значение l. Далее, в указывающую часть этой области записывается ссылка на четвертый элемент структуры (его адрес хранится в переменной insert4). Пятый элемент стека, уже не должен ссылаться на четвертый, он должен указывать на элемент, который указан переменной inserti.

Для вывода элементов стека на экран также используется цикл for. Обход стека возможен только с его конца. На конец стека указывает переменная ir, значение которой присваивается ip. Далее из этого участка памяти извлекается число, записывается в l и выводится на экран. Указателю ir присваивается значение указывающей части ip, т.е. ir теперь указывает на следующий элемент (правильней сказать, предыдущий элемент стека).

Программа на языке Паскаль:

type

intp = ^intrec;

intrec = record

i: integer;

p: intp

end;

var

ip, ir, inserti, insert4, insert5: intp;

k, l: integer;

begin

ir := nil;

writeln('Введите 10 чисел.');

for k := 1 to 10 do begin

readln(l);

new(ip);

ip^.i := l;

ip^.p := ir;

ir := ip;

if k = 5 then begin

insert5 := ip;

insert4 := ip^.p

end

end;

writeln;

writeln('Введите еще одно число.');

readln(l);

new(inserti);

inserti^.i := l;

inserti^.p := insert4;

insert5^.p := inserti;

for k := 1 to 11 do begin

ip := ir;

l := ip^.i;

write(' ',l);

ir := ip^.p;

dispose(ip)

end;

readln

end.