Фундаментальные алгоритмы и структуры данных в Delphi | страница 73




var

SLNodeManager : TtdNodeManager;


Все методы класса односвязного списка можно разбить на две категории: методы, действующие по последовательной схеме (MoveBeforeFirst, InsertAtCursor и т.д.), и методы, которые работают со списком как с массивом (свойство Items, методы Delete, IndexOf и т.д.). Рассмотрим сначала методы первой группы, поскольку мы уже говорили о принципе их работы в начале главы при описании связных списков. Для упрощения реализации мы не только храним курсор (т.е. указатель на текущий узел) в объекте, но и родительский объект курсора (т.е. указатель на родительский объект текущего курсора). Такая схема позволяет упростить методы вставки и удаления элементов.

Листинг 3.9. Стандартные операции со связным списком для класса TtdSingleLinkList


procedure TtdSingleLinkList.Clear;

var

Temp : PslNode;

begin

{удалить все узлы, за исключением начального; при возможности освободить все данные}

Temp := FHead^.slnNext;

while (Temp <> nil) do

begin

FHead^.slnNext := Temp^.slnNext;

if Assigned(FDispose) then

FDispose(Temp^.slnData);

SLNodeManager.FreeNode(Temp);

Temp := FHead^.slnNext;

end;

FCount := 0;

MoveBeforeFirst;

end;


procedure TtdSingleLinkList.DeleteAtCursor;

begin

if (FCursor = nil) or (FCursor = FHead) then

sllError(tdeListCannotDelete, 'Delete');

{удалить все элементы}

if Assigned(FDispose) then

FDispose(FCursor^.slnData);

{удалить ссылки на узел и удалить сам узел}

FParent^.slnNext := FCursor^.slnNext;

SLNodeManager.FreeNode(FCursor);

FCursor := FParent^.slnNext;

dec(FCount);

end;


function TtdSingleLinkList.Examine : pointer;

begin

if (FCursor = nil) or (FCursor = FHead) then

sllError(tdeListCannotExamine, 'Examine');

{вернуть данные с позиции курсора}

Result := FCursor^.slnData;

end;


procedure TtdSingleLinkList.InsertAtCursor(aItem : pointer);

var

NewNode : PslNode;

begin

{убедиться, что вставка производится не перед первой позицией; если курсор находится перед первой позицией, переместить его на одну позицию вперед}

if (FCursor = FHead) then

MoveNext;

{распределить новый узел и вставить его в позицию курсора}

NewNode := PslNode (SLNodeManager.AllocNode);

NewNode^.slnData := aItem;

NewNode^.slnNext := FCursor;

FParent^.slnNext := NewNode;

FCursor := NewNode;

inc(FCount);

end;


function TtdSingleLinkList.IsAfterLast : boolean;

begin

Result := FCursor;

nil;

end;


function TtdSingleLinkList.IsBeforeFirst : boolean;

begin

Result := FCursor = FHead;

end;


function TtdSingleLinkList.IsEmpty : boolean;

begin

Result := (Count = 0);