ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ




ДИНАМИЧЕСКИЕ ПЕРЕМЕННЫЕ

 

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

В отличие от таких статических переменных в программах, написанных на языке ПАСКАЛЬ, могут быть созданы динамические переменные. Основное свойство динамических переменных заключается в том, что они создаются и память для них выделяется во время выполнения программы.

Размещаются динамические переменные в динамической области памяти (heap - области).

Динамическая переменная не указывается явно в описаниях переменных и к ней нельзя обратиться по имени. Доступ к таким переменным осуществляется с помощью указателей и ссылок.

 

Работа с динамической областью памяти в TURBO PASCAL реализуется с помощью процедур и функций New, Dispose, GetMem, FreeMem, Mark, Release, MaxAvail, MemAvail, SizeOf.

Процедура New(var p: Pointer) выделяет место в динамической области памяти для размещения динамической переменной p^ и ее адрес присваивает указателю p.

Процедура Dispose(var p: Pointer) освобождает участок памяти, выделенный для размещения динамической переменной процедурой New, и значение указателя p становится неопределенным.

Проуедура GetMem(var p: Pointer; size: Word) выделяет участок памяти в heap - области, присваивает адрес его начала указателю p, размер участка в байтах задается параметром size.

Процедура FreeMem(var p: Pointer; size: Word) освобождает участок памяти, адрес начала которого определен указателем p, а размер - параметром size. Значение указателя p становится неопределенным.

Процедура Mark(var p: Pointer) записывает в указатель p адрес начала участка свободной динамической памяти на момент ее вызова.

Процедура Release(var p: Pointer) освобождает участок динамической памяти, начиная с адреса, записанного в указатель p процедурой Mark, т.е. очищает ту динамическую память, которая была занята после вызова процедуры Mark.

Функция MaxAvail: Longint возвращает длину в байтах самого длинного свободного участка динамической памяти.

Функция MemAvail: Longint полный объем свободной динамической памяти в байтах.

Вспомогательная функция SizeOf(X): Word возвращает объем в байтах, занимаемый X, причем X может быть либо именем переменной любого типа, либо именем типа.

 

Рассмотрим некоторые примеры работы с указателями.

var

p1, p2: ^Integer; {Здесь p1 и p2 - указатели или переменные ссылочного типа}

 

p1:=NIL; p2:=NIL; {После выполнения этих операторов присваивания указатели p1 и p2 не

будут ссылаться ни на какой конкретный объект}

New(p1); New(p2);

Процедура New(p1) выполняет следующие действия:

-в памяти ЭВМ выделяется участок для размещения величины целого типа;

-адрес этого участка присваивается переменной p1:

г===== г=====

¦ *--¦--------->¦ ¦

L=====- L=====-

p1 p1^

Аналогично, процедура New(p2) обеспечит выделение участка памяти, адрес которого будет записан в p2:

г===== г=====

¦ *--¦--------->¦ ¦

L=====- L=====-

p2 p2^

 

После выполнения операторов присваивания

p1^:=2; p2^:=4;

в выделенные участки памяти будут записаны значения 2 и 4 соответственно:

г===== г=====

¦ *--¦--------->¦ 2 ¦

L=====- L=====-

p1 p1^

 

г===== г=====

¦ *--¦--------->¦ 4 ¦

L=====- L=====-

p2 p2^

В результате выполнения оператора присваивания

p1^:=p2^;

в участок памяти, на который ссылается указатель p1, будет записано значение 4:

г===== г=====

¦ *--¦--------->¦ 4 ¦

L=====- L=====-

p1 p1^

 

г===== г=====

¦ *--¦--------->¦ 4 ¦

L=====- L=====-

p2 p2^

 

После выполнения оператора присваивания

p2:=p1;

оба указателя будут содержать адрес первого участка памяти:

г===== г=====

¦ *--¦--------->¦ 4 ¦

L=====- --->L=====-

p1 ¦ p1^ p2^

¦

г===== ¦

¦ *--¦-------

L=====-

p2

 

Переменные p1^, p2^ являются динамическими, так как память для них выделяется в процессе выполнения программы с помощью процедуры New.

Динамические переменные могут входить в состав выражений, например:

p1^:=p1^+8; Write('p1^=',p1^:3);

 

Пример. В результате выполнения программы:

 

Program DemoPointer;

var p1,p2,p3:^Integer;

begin

p1:=NIL; p2:=NIL; p3:=NIL;

New(p1); New(p2); New(p3);

p1^:=2; p2^:=4;

p3^:=p1^+Sqr(p2^);

writeln('p1^=',p1^:3,' p2^=',p2^:3,' p3^=',p3^:3);

p1:=p2;

writeln('p1^=',p1^:3,' p2^=',p2^:3)

end.

 

на экран дисплея будут выведены результаты:

p1^= 2 p2^= 4 p3^= 18

p1^= 4 p2^= 4


 

ДИНАМИЧЕСКИЕ СТРУКТУРЫДАННЫХ

Структурированные типы данных, такие, как массивы, множества, записи, представляют собой статические структуры, так как их размеры неизменны в течение всего времени выполнения программы.

Часто требуется, чтобы структуры данных меняли свои размеры в ходе решения задачи. Такие структуры данных называются динамическими, к ним относятся стеки, очереди, списки, деревья и другие. Описание динамических структур с помощью массивов, записей и файлов приводит к

неэкономному использованию памяти ЭВМ и увеличивает время решения задач.

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

Поле данных может быть переменной, массивом, множеством или записью.

Для дальнейшего рассмотрения представим отдельную компоненту в виде:

D
p

где поле p - указатель; поле D - данные.

Описание этой компоненты дадим следующим образом:

 

type

Pointer = ^Comp;

Comp = record

D:T;

pNext: Pointer

end;

 

здесь T - тип данных.

Рассмотрим основные правила работы с динамическими структурами данных типа стек, очередь и список, базируясь на приведенное описание компоненты.

 


 

СТЕКИ

Стеком называется динамическая структура данных, добавление компоненты в которую и исключение компоненты из которой производится из одного конца, называемого вершиной стека. Стек работает по принципу

LIFO (Last-In, First-Out) - поступивший последним, обслуживается первым.

Обычно над стеками выполняется три операции:

-начальное формирование стека (запись первой компоненты);

-добавление компоненты в стек;

-выборка компоненты (удаление).

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

var pTop, pAux: Pointer;

где pTop - указатель вершины стека; pAux - вспомогательный указатель.

Начальное формирование стека выполняется следующими операторами:

г===== г=====

New(pTop); ¦ *--¦--- ¦ ¦

L=====- ¦ ¦=====¦

pTop L-->¦ ¦

L=====-

г===== г=====

pTop^.pNext:=NIL; ¦ *--¦--- ¦ ¦

L=====- ¦ ¦=====¦

pTop L-->¦ NIL ¦

L=====-

г===== г=====

pTop^.D:=D1; ¦ *--¦--- ¦ D1 ¦

L=====- ¦ ¦=====¦

pTop L-->¦ NIL ¦

L=====-

Последний оператор или группа операторов записывает содержимое поля данных первой компоненты.

Добавление компоненты в стек производится с использованием вспомогательного указателя:

г===== г===== г=====

New(pAux); ¦ *--¦--- ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦ L=====-

pTop ¦ ¦ ¦<--- pAux

¦ L=====-

¦

¦ г=====

¦ ¦ D1 ¦

¦ ¦=====¦

L-->¦ NIL ¦

L=====-

 

г===== г===== г=====

pAux^.pNext:=pTop; ¦ *--¦--- ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦<--- L=====-

pTop ¦ ¦ *--¦- pAux

¦ L=====- ¦

¦ ¦

¦ г===== ¦

¦ ¦ D1 ¦ ¦

¦ ¦=====¦ ¦

L-->¦ NIL ¦<-

L=====-

 

г===== г===== г=====

pTop:=pAux; ¦ *--¦--- ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦<--- L=====-

pTop L-->¦ *--¦- pAux

L=====- ¦

¦

г===== ¦

¦ D1 ¦ ¦

¦=====¦ ¦

¦ NIL ¦<-

L=====-

 

г===== г=====

pTop^.D:=D2; ¦ *--¦--- ¦ D2 ¦

L=====- ¦ ¦=====¦

pTop L-->¦ *--¦-

L=====- ¦

¦

г===== ¦

¦ D1 ¦ ¦

¦=====¦ ¦

¦ NIL ¦<-

L=====-

Добавление последующих компонент производится аналогично.

Рассмотрим процесс выборки компонент из стека. Пусть к моменту начала выборки стек содержит три компоненты:

г===== г=====

¦ *--¦--- ¦ D3 ¦

L=====- ¦ ¦=====¦

pTop L-->¦ *--¦-

L=====- ¦

¦

г===== ¦

¦ D2 ¦ ¦

¦=====¦ ¦

--¦--* ¦<-

¦ L=====-

¦

¦ г=====

¦ ¦ D1 ¦

¦ ¦=====¦

L>¦ NIL ¦

L=====-

Первый оператор или группа операторов осуществляет чтение данных из компоненты - вершины стека. Второй оператор изменяет значение указателя вершины стека:

 

г===== г=====

D3:=pTop^.D; ¦ * --¦--- ¦ D3 ¦

pTop:=pTop^.pNext; L=====- ¦ ¦=====¦

pTop ¦ ¦ ¦

¦ L=====-

¦

¦ г=====

¦ ¦ D2 ¦

¦ ¦=====¦

L-->¦ * --¦-

L=====- ¦

¦

г===== ¦

¦ D1 ¦ ¦

¦=====¦ ¦

¦ NIL ¦<-

L=====-

Как видно из рисунка, при чтении компонента удаляется из стека.

 

 


 

Пример. Составить программу, которая формирует стек, добавляет в него произвольное количество компонент, а затем читает все компоненты и выводит их на экран дисплея, В качестве данных взять строку символов. Ввод данных - с клавиатуры дисплея, признак конца ввода – строка символов END.

 

Program STACK;

uses Crt;

type

Alfa= String[10];

PComp= ^Comp;

Comp= Record

sD: Alfa;

pNext: PComp

end;

var

pTop: PComp;

sC: Alfa;

Procedure CreateStack(var pTop: PComp; var sC: Alfa);

begin

New(pTop);

pTop^.pNext:=NIL;

pTop^.sD:=sC

end;

Procedure AddComp(var pTop: PComp; var sC: Alfa);

var pAux: PComp;

begin

NEW(pAux);

pAux^.pNext:=pTop;

pTop:=pAux;

pTop^.sD:=sC

end;

Procedure DelComp(var pTop: PComp; var sC:ALFA);

begin

sC:=pTop^.sD;

pTop:=pTop^.pNext

end;

begin

Clrscr;

writeln(' ВВЕДИ СТРОКУ ');

readln(sC);

CreateStack(pTop,sC);

repeat

writeln(' ВВЕДИ СТРОКУ ');

readln(sC);

AddComp(pTop,sC)

until sC='END';

writeln('****** ВЫВОД РЕЗУЛЬТАТОВ ******');

repeat

DelComp(pTop,sC);

writeln(sC);

until pTop = NIL

end.


 

ОЧЕРЕДИ

 

Очередью называется динамическая структура данных, добавление компоненты в которую производится в один конец, а выборка осуществляется с другого конца. Очередь работает по принципу:

FIFO (First-In, First-Out) - поступивший первым, обслуживается первым.

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

Описание компоненты очереди и переменных типа указатель дадим следующим образом:

 

type

PComp=^Comp;

Comp=record

D:T;

pNext:PComp

end;

var

pBegin, pEnd, pAux: PComp;

 

где pBegin - указатель начала очереди, pEnd - указатель конца очереди, pAux - вспомогательный указатель.

Тип Т определяет тип данных компоненты очереди.

Начальное формирование очереди выполняется следующими операторами:

 

г===== г===== г=====

New(pBegin); ¦ *--¦--- ¦ ¦ ¦ ¦

L=====- ¦ ¦=====¦ L=====-

pBegin L-->¦ ¦ pEnd

L=====-

г===== г===== г=====

pBegin^.pNext:=NIL; ¦ *--¦--- ¦ ¦ ¦ ¦

L=====- ¦ ¦=====¦ L=====-

pBegin L-->¦ NIL ¦ pEnd

L=====-

г===== г===== г=====

pBegin^.D:=D1; ¦ *--¦--- ¦ D1 ¦ ¦ ¦

L=====- ¦ ¦=====¦ L=====-

pBegin L-->¦ NIL ¦ pEnd

L=====-

г===== г===== г=====

pEnd:=pBegin; ¦ *--¦--- ¦ D1 ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦ L=====-

pBegin L-->¦ NIL ¦<--- pEnd

L=====-

 

Добавление компоненты в очередь производится в конец очереди:

New(pAux);

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ----¦--* ¦ ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦ L=====- ¦=====¦ ¦ L=====-

pBegin L-->¦ NIL ¦<--- pEnd ¦ ¦<--- pAux

L=====- L=====-

pAux^.pNext:=NIL;

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ----¦--* ¦ ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦ L=====- ¦=====¦ ¦ L=====-

pBegin L-->¦ NIL ¦<--- pEnd ¦ NIL ¦<--- pAux

L=====- L=====-

pBegin^.pNext:=pAux;

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ----¦--* ¦ ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦ L=====- ¦=====¦ ¦ L=====-

pBegin L-->¦ * ¦<--- pEnd ¦ NIL ¦<--- pAux

L=====- L=====-

¦ ^

¦ ¦

L----------------------------

pEnd:=pAux;

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ¦ *--¦--- ¦ ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ L=====- ¦ ¦=====¦ ¦ L=====-

pBegin L-->¦ * ¦ pEnd L-->¦ NIL ¦<--- pAux

L=====- L=====-

¦ ^

¦ ¦

L----------------------------

pEnd^.D:=D2;

г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ¦ D2 ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦=====¦ ¦ L=====-

pBegin L-->¦ *--¦-------------------->¦ NIL ¦<--- pEnd

L=====- L=====-

Добавление последующих компонент производится аналогично.

Выборка компоненты из очереди осуществляется из начала очереди, одновременно компонента исключается из очереди. Пусть в памяти ЭВМ сформирована очередь, состоящая из трех элементов:

 

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ¦ D2 ¦ ¦ D3 ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦=====¦ ¦=====¦ ¦ L=====-

pBegin L-->¦ *--¦------>¦ *--¦------>¦ NIL ¦<--- pEnd

L=====- L=====- L=====-

 

Выборка компоненты выполняется следующими операторами:

D1:=pBegin^.D;

pBegin:=pBegin^.pNext;

г===== г===== г===== г===== г=====

¦ *--¦--- ¦ D1 ¦ ¦ D2 ¦ ¦ D3 ¦ ----¦--* ¦

L=====- ¦ ¦=====¦ ¦=====¦ ¦=====¦ ¦ L=====-

pBegin ¦ ¦ ¦ --->¦ *--¦------>¦ NIL ¦<--- pEnd

¦ L=====- ¦ L=====- L=====-

¦ ¦

L--------------

 


Пример. Составить программу, которая формирует очередь, добавляет в нее произвольное количество компонент, а затем читает все компоненты и выводит их на экран дисплея. В качестве данных взять строку символов. Ввод данных - с клавиатуры дисплея, признак конца ввода - строка символов END.

 

Program QUEUE;

uses Crt;

type

Alfa= String[10];

PComp= ^Comp;

Comp= record

sD:Alfa;

pNext:PComp

end;

var

pBegin, pEnd: PComp;

sC: Alfa;

Procedure CreateQueue(var pBegin,pEnd: PComp; var sC: Alfa);

begin

New(pBegin);

pBegin^.pNext:=NIL;

pBegin^.sD:=sC;

pEnd:=pBegin

end;

Procedure AddQueue(var pEnd:PComp; var sC:Alfa);

var pAux: PComp;

begin

New(pAux);

pAux^.pNext:=NIL;

pEnd^.pNext:=pAux;

pEnd:=pAux;

pEnd^.sD:=sC

end;

Procedure DelQueue(var pBegin: PComp; var sC: Alfa);

begin

sC:=pBegin^.sD;

pBegin:=pBegin^.pNext

end;

begin

Clrscr;

writeln(' ВВЕДИ СТРОКУ ');

readln(sC);

CreateQueue(pBegin,pEnd,sC);

repeat

writeln(' ВВЕДИ СТРОКУ ');

readln(sC);

AddQueue(pEnd,sC)

until sC='END';

writeln(' ***** ВЫВОД РЕЗУЛЬТАТОВ *****');

repeat

DelQueue(pBegin,sC);

writeln(sC);

until pBegin=NIL

end.


 

ЛИНЕЙНЫЕ СПИСКИ В стеки или очереди компоненты можно добавлять только в какой-либо один конец структуры данных, это относится и к извлечению компонент. Связный (линейный) список является структурой данных, в произвольно выбранное место которого могут включаться данные, а также изыматься оттуда.Каждая компонента списка определяется ключом. Обычно ключ - либо число, либо строка символов. Ключ располагается в поле данных компоненты, он может занимать как отдельное поле записи, так и быть частью поля записи.Основные отличия связного списка от стека и очереди следующие: -для чтения доступна любая компонента списка; -новые компоненты можно добавлять в любое место списка; -при чтении компонента не удаляется из списка.Над списками выполняются следующие операции: -начальное формирование списка (запись первой компоненты); -добавление компоненты в конец списка; -чтение компоненты с заданным ключом; -вставка компоненты в заданное место списка (обычно после компоненты с заданным ключом); -исключение компоненты с заданным ключом из списка.Для формирования списка и работы с ним необходимо иметь пять переменных типа указатель, первая из которых определяет начало списка, вторая - конец списка, остальные- вспомогательные.Описание компоненты списка и переменных типа указатель дадим следующим образом: type PComp= ^Comp; Comp= record D:T; pNext:PComp end; var pBegin, pEnd, pCKey, pPreComp, pAux: PComp; где pBegin - указатель начала списка, pEnd - указатель конца списка, pCKey, pPreComp, pAux - вспомогательные указатели.Начальное формирование списка, добавление компонент в конец списка выполняется так же, как и при формировании очереди. г===== г===== г===== г===== г===== г=====¦ *--¦- ¦ D1 ¦ ¦ D2 ¦ ¦ DN1 ¦ ¦ DN ¦ --¦--* ¦L=====- ¦ ¦=====¦ ¦=====¦ ¦=====¦ ¦=====¦ ¦ L=====-pBegin L-->¦ *--¦--->¦ *--¦-....->¦ *--¦--->¦ NIL ¦<-- pEnd L=====- L=====- L=====- L=====- Для чтения и вставки компоненты по ключу необходимо выполнить поиск компоненты с заданным ключом: pCKey:=pBegin; while (pCKey<>NIL) and (Key<>pCKey^.D) DO pCKey:=pCKey^.pNext; Здесь Key - ключ, тип которого совпадает с типом данных компоненты.После выполнения этих операторов указатель pСKey будет определять компоненту с заданным ключом или такая компонента не будет найдена.Пусть pCKey определяет компоненту с заданным ключом. Вставка новой компоненты выполняется следующими операторами: New(pAux); г=== pAux^.D:= DK1; ---¦-* ¦ ¦ L===- ¦ pCKey ¦г=== г=== г=== г=== г=== г===¦ *-¦-- ¦D1 ¦ ¦Key¦ ¦KK1¦ ¦DN ¦ ---¦-* ¦L===- ¦ ¦===¦ ¦===¦ ¦===¦ ¦===¦ ¦ L===-pBegin L->¦ *-¦-...->¦ *-¦---->¦ *-¦-...->¦NIL¦<-- pEnd L===- L===- L===- L===- г=== г=== ¦DK1¦ ---¦-* ¦ ¦===¦ ¦ L===- ¦ ¦<-- pAux L===- pAux^.pNext:=pCKey^.pNext; pCKey^.pNext:=pAux; г=== ---¦-* ¦ ¦ L===- ¦ pCKey ¦г=== г=== г=== г=== г=== г===¦ *-¦-- ¦D1 ¦ ¦Key¦ ¦KK1¦ ¦DN ¦ ---¦-* ¦L===- ¦ ¦===¦ ¦===¦ ¦===¦ ¦===¦ ¦ L===-pBegin L->¦ *-¦-...->¦ * ¦ ¦ *-¦-...->¦NIL¦<-- pEnd L===- L===- L===- L===- ¦ ^ ¦ ¦ г=== г=== ¦ ¦ ¦DK1¦ ---¦-* ¦ ¦ L----------¦===¦ ¦ L===- L------------------->¦-* ¦<-- pAux L===- Для удаления компоненты с заданным ключом необходимо при поиске нужной компоненты помнить адрес предшествующей: pCKey:=pBegin; while (pCKey<>NIL) and (Key<>pCKey^.D) do begin pPreComp:=pCKey; pCKey:=pCKey^.pNext end; Здесь указатель pCKey определяет компоненту с заданным ключом, указатель pPreComp содержит адрес предидущей компоненты. Удаление компоненты с ключом Key выполняется оператором: pPreComp^.pNext:=pCKey^.pNext; pPreComp pCKey г=== г=== ¦ * ¦ ¦ * ¦ L===- L===- ¦ ¦ ¦ ¦ ¦ ¦г=== г=== г=== г=== г=== г=== г===¦ *-¦-- ¦D1 ¦ ¦KK1¦ ¦Key¦ ¦KK2¦ ¦DN ¦ ---¦-* ¦L===- ¦ ¦===¦ ¦===¦ ¦===¦ ¦===¦ ¦===¦ ¦ L===-pBegin L->¦ *-¦-...->¦ *-¦- ¦ *-¦--->¦ *-¦-...->¦NIL¦<-- pEnd L===- L===- ¦ L===- L===- L===- ¦ ^ ¦ ¦ L---------------

 

Пример. Составить программу, которая формирует список, добавляет в него произвольное количество компонент, выполняет вставку и удаление компоненты по ключу, а затем читает и выводит весь список на экран дисплея. В качестве данных взять строку символов. Ввод данных – с клавиатуры дисплея, признак конца ввода - строка символов END. Program LISTLINKED; uses Crt; type Alfa= String[10]; PComp= ^Comp; Comp= record sD:Alfa; pNext:PComp end; var pBegin, pEnd, pAux, pCKey, pPreComp: PComp; sC, sKey: Alfa; bCond: Boolean; Procedure CreateLL(var pBegin,pEnd: PComp; var sC: Alfa); begin New(pBegin); pBegin^.pNext:=NIL; pBegin^.sD:=sC; pEnd:=pBegin end; Procedure AddLL(var pEnd: PComp; var sC: Alfa); var pAux: PComp; begin New(pAux); pAux^.pNext:=NIL; pEnd^.pNext:=pAux; pEnd:=pAux; pEnd^.sD:=sC end; Procedure Find(var sKey: Alfa; var pBegin,pCKey,pPreComp: PComp; var bCond: Boolean); begin pCKey:=pBegin; while (pCKey <> NIL) and (sKey <> pCKey^.D) do begin pPreComp:=pCKey; pCKey:=pCKey^.pNext end; if (pCKey = NIL) and (sKey <> pCKey^.sD) then bCond:=FALSE else bCond:=TRUE end; Procedure InsComp(var sKey,sC: Alfa); var pAux:PComp; begin Find(sKey,pBegin,pCKey,pPreComp,bCond); New(pAux); pAux^.sD:=sC; pAux^.pNext:=pCKey^.pNext; pCKey^.pNext:=pAux end; Procedure DelComp(var sKey: Alfa; var pBegin: PComp); begin Find(sKey,pBegin,pCKey,pPreComp,bCond); pPreComp^.pNext:=pCKey^.pNext end; begin ClrScr; writeln(' ВВЕДИ СТРОКУ '); readln(sC); CreateLL(pBegin,pEnd,sC); repeat writeln('ВВЕДИ СТРОКУ '); readln(sC); AddLL(pEnd,sC) until sC='END'; writeln(' ***** ВЫВОД ИСХОДНОГО СПИСКА *****'); pAux:=pBegin; repeat writeln(pAux^.sD); pAux:=pAux^.pNext; until pAux=NIL; writeln; writeln('ВВЕДИ КЛЮЧ ДЛЯ ВСТАВКИ СТРОКИ'); readln(sKey); writeln('ВВЕДИ ВСТАВЛЯЕМУЮ СТРОКУ'); readln(sC); InsComp(sKey,sC); writeln; writeln('ВВЕДИ КЛЮЧ УДАЛЯЕМОЙ СТРОКИ'); readln(sKey); DelComp(sKey,pBegin); writeln; writeln(' ***** ВЫВОД ИЗМЕНЕННОГО СПИСКА *****'); pAux:=pBegin; repeat writeln(pAux^.sD); pAux:=pAux^.pNext; until pAux=NIL end.

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-26 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: