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

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

Жанры

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

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

Шрифт:

Метод Clear очень похож на метод Delete, за исключением того, что мы просто стандартным образом удаляем все узлы из каждого связного списка (естественно, за исключением заглавных узлов).

Листинг 7.16. Очистка хеш-таблицы TtdHashTableChained

procedure TtdHashTableChained.Clear;

var

Inx : integer;

Temp, Walker : PHashedItem;

begin

for Inx := 0 to pred(FTable.Count) do

begin

Walker := PHashedItem(FTable.List^[Inx])^.hiNext;

while (Walker <> nil) do

begin

if Assigned(FDispose) then

FDispose(Walker^.hiItem);

{$IFDEF Delphi1}

DisposeStr(Walker^.hiKey);

{$ELSE}

Walker^.hiKey := '';

{$ENDIF}

Temp := Walker;

Walker := Walker^.hiNext;

FNodeMgr.FreeNode(Temp);

end;

PHashedItem(FTable.List^[Inx])^.hiNext := nil;

end;

FCount := 0;

end;

Метод Find

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

Листинг 7.17. Поиск элемента в хеш-таблице со связыванием

function TtdHashTableChained.Find(const aKey : string; var aItem : pointer): boolean;

var

Inx : integer;

Parent : pointer;

begin

if htcFindPrim(aKey, Inx, Parent) then begin

Result := true;

aItem := PHashedItem(Parent)^.hiNext^.hiItem;

end

else begin

Result := false;

aItem := nil;

end;

end;

Единственная небольшая сложность состоит в том, что метод htcFindPrim возвращает родительский узел действительно интересующего нас узла.

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

Листинг 7.18. Увеличение хеш-таблицы со связыванием

procedure TtdHashTableChained.htcGrowTable;

begin

{увеличить размер таблицы примерно в два раза по сравнению с предыдущим размером}

htcAlterTableSize(TDGetClosestPrime(succ(FTable.Count * 2)));

end;

procedure TtdHashTableChained.htcAlterTableSize(aNewTableSize : integer);

var

Inx : integer;

OldTable : TList;

Walker, Temp : PHashedItem;

begin

{сохранить старую таблицу}

OldTable := FTable;

{распределить новую таблицу}

FTable := TList.Create;

try

FTable.Count := aNewTableSize;

htcAllocHeads(FTable);

{считывать старую таблицу и перенести ключи и элементы в новую таблицу посредством их вставки}

FCount := 0;

for Inx := 0 to pred(OldTable.Count) do

begin

Walker := PHashedItem(OldTable.List^[Inx])^.hiNext;

while (Walker <> nil) do

begin

{$IFDEF Delphi1}

Insert(Walker^.hiKey^, Walker^.hiItem);

{$ELSE}

Insert(Walker^.hiKey, Walker^.hiItem);

{$ENDIF}

Walker := Walker^.hiNext;

end;

end;

except

{предпринять

попытку очистки и сохранения хеш-таблицы в непротиворечивом состоянии в случае возникновения исключения}

Clear;

htcFreeHeads(FTable);

FTable.Free;

FTable := OldTable;

raise;

end;

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

for Inx := 0 to pred(01dTable.Count) do

begin

Walker := PHashedItem(OldTable.List^[Inx])^.hiNext;

while (Walker <> nil) do

begin

{$IFDEF Delphi1}

DisposeStr(Walker^.hiKey);

{$ELSE}

Walker^.hiKey := '';

{$ENDIF}

Temp := Walker;

Walker := Walker^.hiNext;

FNodeMgr.FreeNode(Temp);

end;

PHashedItem(OldTable.List^[Inx])^.hiNext := nil;

end;

htcFreeHeads(OldTable);

OldTable.Free;

end;

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

В заключение рассмотрим основной метод, используемый многими методами класса хеш-таблицы - htcFindPrim (листинг 7.19).

Листинг 7.19. Примитив для поиска элемента в хеш-таблице со связыванием

function TtdHashTableChained.htcFindPrim( const aKey : string;

var aInx : integer;

var aParent : pointer): boolean;

var

Inx : integer;

Head, Walker, Parent : PHashedItem;

begin

{вычислить хеш-значение для строки}

Inx := FHashFunc(aKey, FTable.Count);

{предположить, что связный список существует в Inx-ой ячейке}

Head := PHashedItem(FTable.List^[Inx]);

{начать просмотр связного списка с целью поиска ключа}

Parent := Head;

Walker := Head^.hiNext;

while (Walker <> nil) do

begin

{$lFDEFDelphi1}

if (Walker^.hiKey^ = aKey) then begin

{$ELSE}

if (Walker^.hiKey = aKey) then begin

{$ENDIF}

if (ChainUsage = hcuFirst) and (Parent = Head) then begin

Parent^.hiNext := Walker^.hiNext;

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

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Сердце Дракона. Том 11

Клеванский Кирилл Сергеевич
11. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.50
рейтинг книги
Сердце Дракона. Том 11

Первый среди равных. Книга IV

Бор Жорж
4. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IV

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Мастер Разума IV

Кронос Александр
4. Мастер Разума
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер Разума IV

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Кадры решают все

Злотников Роман Валерьевич
2. Элита элит
Фантастика:
боевая фантастика
попаданцы
альтернативная история
8.09
рейтинг книги
Кадры решают все

Плеяда

Суконкин Алексей
Проза:
военная проза
русская классическая проза
5.00
рейтинг книги
Плеяда

Потусторонний. Книга 2

Погуляй Юрий Александрович
2. Господин Артемьев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Потусторонний. Книга 2

Ученик. Книга 4

Первухин Андрей Евгеньевич
4. Ученик
Фантастика:
фэнтези
5.67
рейтинг книги
Ученик. Книга 4

Законник Российской Империи. Том 3

Ткачев Андрей Юрьевич
3. Словом и делом
Фантастика:
городское фэнтези
альтернативная история
аниме
дорама
5.00
рейтинг книги
Законник Российской Империи. Том 3

Ваше Сиятельство 7

Моури Эрли
7. Ваше Сиятельство
Фантастика:
боевая фантастика
аниме
5.00
рейтинг книги
Ваше Сиятельство 7

Война

Валериев Игорь
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Война

Младший сын князя. Том 4

Ткачев Андрей Юрьевич
4. Аналитик
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Младший сын князя. Том 4