Чтение онлайн

на главную - закладки

Жанры

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

Бакнелл Джулиан М.

Шрифт:

Класс двухсвязного списка

Интерфейс класса двухсвязного списка выглядит следующим образом:

Листинг 3.13. Класс TtdDoubleLinkList

TtdDoubleLinkList = class private

FCount : longint;

FCursor : PdlNode;

FCursorIx: longint;

FDispose : TtdDisposeProc;

FHead : PdlNode;

FName : TtdNameString;

FTail : PdlNode;

protected

function dllGetItem(aIndex : longint): pointer;

procedure dllSetItem(aIndex : longint; aItem : pointer);

procedure dllError(aErrorCode : integer;

const aMethodName : TtdNameString);

class procedure dllGetNodeManager;

procedure dllPositionAtNth(aIndex : longint);

public

constructor Create(aDispose : TtdDisposeProc);

destructor Destroy; override;

function Add(aItem : pointer): longint;

procedure Clear;

procedure Delete(aIndex : longint);

procedure DeleteAtCursor;

function Examine : pointer;

function First : pointer;

function IndexOf(aItem : pointer): longint;

procedure Insert(aIndex : longint; aItem : pointer);

procedure InsertAtCursor(aItem : pointer);

function IsAfterLast : boolean;

function IsBeforeFirst : boolean;

function IsEmpty : boolean;

function Last : pointer;

procedure MoveAfterLast;

procedure MoveBeforeFirst;

procedure MoveNext;

procedure MovePrior;

procedure Remove(aItem : pointer);

procedure Sort(aCompare : TtdCompareFunc);

property Count : longint read FCount;

property Items[aIndex : longint] : pointer

read dllGetItem write dllSetItem; default;

property Name : TtdNameString read FName write FName;

end;

Как

видите, этот интерфейс очень похож на интерфейс класса TtdSingleLinkList. Собственно, так и должно быть. Для пользователя должно быть безразлично, какой класс он выбирает, оба они должны работать одинаково. Сам выбор односвязного или двухсвязного списка должен зависеть от назначения. Если большая часть перемещений курсора направлена вперед и доступ к случайным элементам выполняется редко, эффективнее использовать односвязный список. Если же высока вероятность того, что список будет проходиться как в прямом, так и в обратном направлениях, то, несмотря на большие требования к памяти, лучше выбрать двухсвязный список. Если же ожидается, что доступ к элементам списка будет осуществляться, в основном, в случайном порядке, выберите класс TList, несмотря на то, что он требует несколько большего времени на вставку и удаление элемента.

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

Конструктор Create распределяет при помощи диспетчера узлов еще один дополнительный фиктивный узел - FTail. Как упоминалось во введении к двухсвязным спискам, он предназначен для обозначения конца списка. Начальный и конечный фиктивные узлы вначале будут связаны друг с другом, т.е. ссылка Next начального узла указывает на конечный узел, а ссылка Prior конечного узла - на начальный узел. Естественно, деструктор Destroy будет удалять фиктивный конечный узел и возвращать его вместе с начальным узлов в диспетчер узлов.

Листинг 3.14. Конструктор Create и деструктор Destroy класса TtdDoubleLinkList

constructor TtdDoubleLinkList.Create;

begin

inherited Create;

{сохранить процедуру удаления}

FDispose :=aDispose;

{получить диспетчер узлов}

dllGetNodeManager;

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

FHead := PdlNode (DLNodeManager.AllocNode);

FTail := PdlNode (DLNodeManager.AllocNode);

FHead^.dlnNext := FTail;

FHead^.dlnPrior :=nil;

FHead^.dlnData := nil;

FTail^.dlnNext := nil;

FTail^.dlnPrior := FHead;

FTail^.dlnData := nil;

{установить курсор на начальный узел}

FCursor := FHead;

FCursorIx := -1;

end;

destructor TtdDoiibleLinkList.Destroy;

begin

if (Count <> 0) then

Clear;

DLNodeManager.FreeNode (FHead);

DLNodeManager.FreeNode(FTail);

inherited Destroy;

end;

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

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

procedure TtdDoubleLinkList.Clear;

var

Temp : PdlNode;

begin

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

Temp := FHead^.dlnNext;

while (Temp <> FTail) do

begin

FHead^.dlnNext := Temp^.dlnNext;

if Assigned(FDispose) then

FDispose(Temp^.dlnData);

DLNodeManager.FreeNode(Temp);

Temp := FHead^.dlnNext;

end;

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

FTail^.dlnPrior := FHead;

FCount := 0;

{установить курсор на начальный узел}

FCursor := FHead;

FCursorIx := -1;

end;

procedure TtdDoubleLinkList.DeleteAtCursor;

var

Temp : PdlNode;

begin

{записать в Temp удаляемый узел}

Temp := FCursor;

if (Temp = FHead) or (Temp = FTail) then

dllError(tdeListCannotDelete, 'Delete');

{избавиться от его содержимого}

if Assigned(FDispose) then

FDispose(Temp^.dlnData);

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

Temp^.dlnPrior^.dlnNext := Temp^.dlnNext;

Temp^.dlnNext^.dlnPrior := Temp^.dlnPrior;

FCursor := Temp^.dlnNext;

DLNodeManager.FreeNode(Temp);

dec(FCount);

end;

function TtdDoubleLinkList.Examine : pointer;

begin

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

Поделиться:
Популярные книги

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Неудержимый. Книга XIX

Боярский Андрей
19. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIX

Жена моего брата

Рам Янка
1. Черкасовы-Ольховские
Любовные романы:
современные любовные романы
6.25
рейтинг книги
Жена моего брата

Студент из прошлого тысячелетия

Еслер Андрей
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Студент из прошлого тысячелетия

Совок 4

Агарев Вадим
4. Совок
Фантастика:
попаданцы
альтернативная история
6.29
рейтинг книги
Совок 4

Приручитель женщин-монстров. Том 3

Дорничев Дмитрий
3. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 3

Под маской моего мужа

Рам Янка
Любовные романы:
современные любовные романы
5.67
рейтинг книги
Под маской моего мужа

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Месть бывшему. Замуж за босса

Россиус Анна
3. Власть. Страсть. Любовь
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть бывшему. Замуж за босса

Последний Паладин. Том 7

Саваровский Роман
7. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 7

Я князь. Книга XVIII

Дрейк Сириус
18. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я князь. Книга XVIII

Жандарм 5

Семин Никита
5. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Жандарм 5

Боги, пиво и дурак. Том 3

Горина Юлия Николаевна
3. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 3

Аномальный наследник. Том 1 и Том 2

Тарс Элиан
1. Аномальный наследник
Фантастика:
боевая фантастика
альтернативная история
8.50
рейтинг книги
Аномальный наследник. Том 1 и Том 2