Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
_Delphi_1курс лекции / Тема Динамические структуры данных.doc
Скачиваний:
73
Добавлен:
23.03.2015
Размер:
330.24 Кб
Скачать

Соображения по поводу эффективности

Как и для односвязных списков, предварительно приведем некоторые сообра­жения, касающиеся проблемы эффективности.

Использование начального и конечного узлов

Для односвязного списка было показано, что наличие начального узла суще­ственно упрощало операции вставки и удаления. Соответствующий случай для двухсвязного списка - наличие двух фиктивных узлов: начального и конечного. Они позволяют очень легко выполнять прохождение списка от первого узла к пос­леднему, равно как от последнего к первому. Специальные случаи при этом ис­ключаются.

Стек

Стек— это структура данных, в которой добав­ление новых элементов и удаление существующих производит­ся с одного конца, называемого вершиной стека или другими словами: реализована стратегия доступа " последний пришел – первый ушел" (LIFO – Last In First Out)

Простой пример: детская пирамидка. Процесс сборки и разборки пирамидки подобен процессу функционирования сте­ка. В любой момент времени доступен лишь один элемент стека — верхний. Из определения следует, что извлекать элементы из стека можно только в порядке, об­ратном порядку их добавления в стек.

Основные операции со стеком:

  • запись элемента в стек,

  • изв­лечение элемента из стека,

  • проверка наличия элементов в сте­ке.

Cуществу­ют два варианта реализации стека: первый - на основе односвязного списка, второй - на основе массива.

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

Таким образом, описать стек (элементом данных являются целые числа) можно следующим образом:

Type

DataType=integer;

nodePtr=^node;

node=Record

data: DataType;

next: nodePtr;

End;

Var

st: nodePtr;

Если стек пуст, то значение указателя st равно Nil.

Запись в стек.

Процедура записи элемента в стек должна со­держать два параметра: первый определяет указатель на нача­ло стека, второй — записываемое в стек значение.

Запись в стек производится аналогично вставке нового эле­мента в начало списка:

Procedure WriteStack(Var u:nodePtr; d:DataType);

Var

newNode:nodePtr;

Begin

New(newNode) ;

newNode^.data:=d;

newNode^.next:=u;

u:=newNode;

End;

Извлечение элемента из стека.

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

Procedure ReadStack(Var u:nodePtr; Var d:DataType);

Var

tempNode:nodePtr;

Begin

d:=u^.Data;

tempNode:=u;

u:=u^.Next;

Dispose (tempNode) ;

End;

Недостатком описанной процедуры является предположение о том, что стек не пуст. Для его исправления следует разрабо­тать логическую функцию проверки пустоты обрабатываемого стека и перед использованием процедуры ReadStack проверять наличие элементов в стеке.

Function isFree (u:nodePtr):Boolean;

Begin

If u=Nil Then isFree:=True

Else isFree:= False;

End;

Пример

Написать программу, проверяющую соответствие открывающих и закрывающих скобок типа «(, ), {, }, [, ]» в строке символов.

Для решения задачи определим стек, элементами которого являются символы:

DataType=char;

В процессе решения анализируем символы строки a:string. Если встречена одна из открывающих скобок, то она записыва­ется в стек. При обнаружении закрывающейся скобки, соответ­ствующей скобке, находящейся в вершине стека, последняя удаляется. При несоответствии скобок выдается сообщение об ошибке, которое фиксируется в логической переменной.

Осталось выяснить, как определить, соответствует ли очеред­ная закрывающая скобка скобке, находящейся в вершине стека. Оказывается, что коды соответствующих друг другу скобок отли­чаются не более чем на 2: { } имеют коды 123-125; [ ] — 91-93; () — 40-41, причем код открывающей скобки меньше. То есть выполнение условия If (Ord(a[i])-Ord(stack^ .data))<=2 Then... говорит о соответствии обрабатываемых скобок.

Program Parenth;

Type

DataType=char;

nodePtr=^node;

node=Record

data: DataType;

next: nodePtr;

End;

Var

s:String;

f :Boolean ;

Procedure WriteStack(Var u:nodePtr; d:DataType);

Var

newNode:nodePtr;

Begin

New(newNode) ;

newNode^.data:=d;

newNode^.next:=u;

u:=newNode;

End;

Procedure ReadStack(Var u:nodePtr; Var d:DataType);

Var

tempNode:nodePtr;

Begin

d:=u^.Data;

tempNode:=u;

u:=u^.Next;

Dispose (tempNode) ;

End;

Function isFree (u:nodePtr):Boolean;

Begin

If u=Nil Then

isFree:=True

Else

isFree:= False;

End;

Procedure Solve(a:String;Var pp:Boolean);

Var

head:nodePtr;

i:Integer;

ch:DataType;

Begin

head:=Nil;

pp:=True;

i:=1 ;

While (i<=Length (a)) And pp Do

Begin

If a[i] In ['(','[','{'] Then

WriteStack (head,a [i])

Else

Begin

If a[i] In [')',']','}'] Then

Begin

If not isFree(head) Then

Begin

ReadStack (head,ch);

If ABS (Ord(ch)-Ord(a[i])) >2 Then pp:=False;

End

Else pp:=False;

End;

End;

Inc(i);

End;

if not isFree(head) Then pp:=False

End;

Begin

WriteLn('Введите текст.');

ReadLn(s);

If s<>'' Then

Begin

Solve (s,f) ;

IffThenWriteLn('Строка записана правильно.')

ElseWriteLn('В строке содержится ошибка.');

End

Else

WriteLn('Строка пустая.');

ReadLn;

End.