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

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

Шрифт:

Разделы private и protected содержат еще несколько методов и полей. Во-первых, это методы set и get свойства Items, а, во-вторых, - два метода, предназначенные для выполнения считывания и записи каталога в и из потока. Кроме того, как мы видим, реальным контейнером записей каталога является экземпляр TList.

В листинге 7.21 конструктор создает экземпляр каталога хеш-таблицы, внутренний объект TList и при необходимости выполняет автоматическое считывание из потока.

Листинг 7.21. Создание экземпляра класса TtdHashDirectory

constructor TtdHashDi rector Y.Create(aStrearn : TStream);

begin

Assert(sizeof(pointer) = sizeof(longint), hdErrorMsg(tdePointerLongSize, 1 Create1, 0));

{создать предка}

inherited Create;

{создать каталог как TList}

FList := TList.Create;

FStream := aStream;

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

if (FStream.Size = 0) then begin

FList.Count := 1;

FCount := 1;

FDepth := 0;

end

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

else

hdLoadFromS trearn;

end;

procedure TtdHashDirectory.hdLoadFromStream;

begin

FStream.Seek(0, soFromBeginning);

FStream.ReadBuffer(FDepth, sizeof(FDepth));

FStream.ReadBuffer(FCount, sizeof(FCount));

FList.Count := FCount;

FStream.ReadBuffer(FList.List^, FCount * sizeof(longint));

end;

Я оставил оператор Assert в конструкторе Create. Он проверяет равенство размера указателя размеру значения longint. Это связано с тем, что я немного "схитрил", сохраняя значения каталога непосредственно в TList в виде однотипных указателей. При изменении размера указателя или longint, используемый метод работать не будет. Поэтому, просто на всякий случай, я поместил здесь это утверждение. Если впоследствии компилятор будет генерировать сообщение об ошибке, это можно будет исправить. Если же нет, то во время выполнения будет выводиться сообщение о нарушении утверждения.

А пока что LoadFromStream выполняет минимальную проверку для проверки наличия допустимого каталога в потоке. Поскольку считывание выполняется непосредственно из потока в буфер фиксированного размера, в будущем, возможно, имеет смысл несколько усовершенствовать процесс, включив сигнатуру в поток или добавив проверку с применением циклического избыточного кода и т.п.

Уничтожение экземпляра каталога хеш-таблицы (листинг 7.22) требует считывания его текущего содержимого обратно в поток и освобождения внутреннего объекта TList.

Листинг 7.22. Уничтожение экземпляра класса TtdHashDirectory

destructor TtdHashDirectory.Destroy;

begin

hdStoreToStream;

FList.Free;

inherited Destroy;

end;

procedure TtdHashDirectory.hdStoreToStream;

begin

FStream.Seek(0, soFromBeginning);

FStream.WriteBuffer(FDepth, sizeof(FDepth));

FStream.WriteBuffer(FCount, sizeof(FCount));

FStream.WriteBuffer(FList.List'4, FCount * sizeof(longint));

end;

Методы предка (листинг 723) свойства Items просто извлекают данные, однотипные longint, из внутреннего объекта TList.

Листинг 7.23. Установка и извлечение значений каталога

function TtdHashDirectory.hdGetItem(aInx : integer): longint;

begin

Assert( (0 <= aInx) and (aInx < FList.Count),

hdErrorMsg(tdeIndexOutOfBounds, 'hdGetItem', aInx));

Result := longint(FList.List^[aInx]);

end;

procedure TtdHashDirectory.hdSetItem(aInx : integer;

aValue : longint );

begin

Assert ((0 <= aInx) and (aInx < FList.Count), hdErrorMsg(tdeIndexOutOfBounds, 'hdGetItem', aInx));

FList.List^[aInx] := pointer(aValue);

end;

И, наконец, в листинге 7.24 приведен код интересного метода класса, который вдвое увеличивает размер каталога.

Листинг 7.24. Увеличение вдвое количества записей в каталоге

procedure TtdHashDirectory.DoubleCount;

var

Inx : integer;

begin

{удвоить значение счетчика, увеличить глубину}

FList.Count := FList.Count * 2;

FCount := FCount * 2;

inc(FDepth);

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

for Inx := pred(FList.Count) downto 1 do

FList.List^[Inx] := FList.List^[Inx div 2];

end;

Во-первых, этот метод удваивает значение счетчика элементов во внутреннем объекте TList. Реализация TList гарантирует установку новых элементов в нулевые значения, хотя, как вскоре будет показано, это не имеет никакого значения. Метод удваивает значение внутреннего счетчика и увеличивает значение разрядной глубины. Затем мы копируем и удваиваем все элементы объекта TList (чтобы убедиться, что цикл работает правильно, советуем во время изучения этого материала обращаться к рисункам 7.1 (е) и 7.1 (f)).

  • Читать дальше
  • 1
  • ...
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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