MyBooks.club
Все категории

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

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Джулиан Бакнелл - Фундаментальные алгоритмы и структуры данных в Delphi. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
Фундаментальные алгоритмы и структуры данных в Delphi
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
229
Читать онлайн
Джулиан Бакнелл - Фундаментальные алгоритмы и структуры данных в Delphi

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

Джулиан Бакнелл - Фундаментальные алгоритмы и структуры данных в Delphi - описание и краткое содержание, автор Джулиан Бакнелл, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Книга "Фундаментальные алгоритмы и структуры данных в Delphi" представляет собой уникальное учебное и справочное пособие по наиболее распространенным алгоритмам манипулирования данными, которые зарекомендовали себя как надежные и проверенные многими поколениями программистов. По данным журнала "Delphi Informant" за 2002 год, эта книга была признана сообществом разработчиков прикладных приложений на Delphi как «самая лучшая книга по практическому применению всех версий Delphi».В книге подробно рассматриваются базовые понятия алгоритмов и основополагающие структуры данных, алгоритмы сортировки, поиска, хеширования, синтаксического разбора, сжатия данных, а также многие другие темы, тесно связанные с прикладным программированием. Изобилие тщательно проверенных примеров кода существенно ускоряет не только освоение фундаментальных алгоритмов, но также и способствует более квалифицированному подходу к повседневному программированию.Несмотря на то что книга рассчитана в первую очередь на профессиональных разработчиков приложений на Delphi, она окажет несомненную пользу и начинающим программистам, демонстрируя им приемы и трюки, которые столь популярны у истинных «профи». Все коды примеров, упомянутые в книге, доступны для выгрузки на Web-сайте издательства.

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

Фундаментальные алгоритмы и структуры данных в Delphi - читать книгу онлайн бесплатно, автор Джулиан Бакнелл

-------

Полный код класса TtdNodeManager можно найти на Web-сайте издательства, в разделе материалов. После выгрузки материалов отыщите среди них файл TDNdeMgr.pas.

Перед тем как вернуться к дальнейшим исследованиям односвязных списков, с которых мы начали наши рассуждения, отметим несколько недостатков класса TtdNodeManager. Первое, что следует отметить - это то, что метод FreeNode не проверяет, принадлежит ли освобождаемый узел к требуемому классу, т.е. находится ли он на странице, контролируемой классом. Это основной вопрос правильного функционирования класса. Если у класса есть узел, который не принадлежит к данному классу, он может иметь неверную длину (что в итоге может привести к перезаписи памяти) или может принадлежать к другому классу, который, возможно, очистит страницу, содержащую узел, и т.д. При отладке имеет смысл проводить проверку принадлежности к классу всех освобождаемых узлов. Реализация, содержащаяся в рамках сопровождающих книгу материалов, включает специальный код проверки при условии, что модель будет компилироваться с использованием утверждений.

Вторая проблема вызвана тем, что мы легко можем удалить экземпляр диспетчера узлов до удаления объектов, которые эти узлы используют. Это приведет к возникновению неизвестных ошибок. Только достаточная внимательность во время программирования может нас избавить от такого рода ошибок.

(Кстати, в качестве простого доказательства того, что мы не зря потеряли время на реализацию диспетчера узлов, можно сказать, что тесты по распределению и освобождению одного миллиона узлов показали, что диспетчер узлов работает в 3-4 раза быстрее, чем диспетчер кучи Delphi.)

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

Перед тем как приступить к реализации класса TtdSingleLinkList для представления односвязного списка, рассмотрим несколько вводных замечаний.

Начнем с самого начала. Как уже упоминалось, было бы очень удобно использовать связный список, не беспокоясь о его узлах. Хотелось бы, чтобы класс связного списка мог работать с любыми типами указателей, подобно классу TList. Для получения доступа к элементам связного списка было бы желательно использовать индекс (несмотря на то что это может негативно сказаться на быстродействии), но еще лучше было бы использовать терминологию баз данных. Так, в связном списке можно использовать курсор, который указывает на "текущий" элемент списка. Тогда можно было бы написать методы для позиционирования курсора перед любым элементом списка, перемещения курсора на следующий элемент, вставки и удаления элемента в позиции курсора и т.д. Поскольку мы создаем связный список в виде класса, мы можем работать с родительским объектом текущего элемента, что позволит запрограммировать метод Insert так, как он реализован в TList (т.е. за счет перемещения текущего элемента и всех последующих элементов на одну позицию и вставки в освободившееся место нового элемента). Аналогично можно реализовать и метод Delete.

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


Листинг 3.7. Класс TtdSingleLinkList


TtdSingleLinkList = class private

FCount : longint;

FCursor : PslNode;

FCursorIx: longint;

FDispose : TtdDisposeProc;

FHead : PslNode;

FNanie : TtdNameString;

FParent : PslNode;

protected


function sllGetItem(aIndex : longint): pointer;

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

procedure sllError(aErrorCode : integer;

const aMethodName : TtdNameString);

class procedure sllGetNodeManager;

procedure sllPositionAtNth(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 MoveBeforeFirst;

procedure MoveNext;

procedure Remove(aItem : pointer);

procedure Sort(aCompare : TtdCompareFunc);

property Count : longint read FCount;

property Items[aIndex : longint] : pointer read sllGetItem write sllSetItem; default;

property Name : TtdNameString read FName write FName;

end;


Несмотря на то что названия методов соответствуют стандарту TList, появилось несколько новых методов. Метод MoveBeforeFirst помещает курсор перед всеми элементами связного списка. IsBeforeFirst и IsAfterLast возвращают True, если курсор находится, соответственно, перед всеми элементами или после всех элементов списка. Метод MoveNext перемещает курсор на следующий элемент списка. Свойство Items аналогично соответствующему свойству списка TList: элементы нумеруются от 0 до Count-1.

Конструктор Create проверяет, создан ли экземпляр диспетчера узлов, а затем распределяет память для узла, который будет фиктивным начальным узлом. Затем курсор помещается перед всеми узлами (поскольку в списке еще нет узлов, это совсем несложно). Деструктор Destroy очищает связный список и освобождает фиктивный начальный узел, выделенный конструктором Create.

Листинг 3.8. Конструктор и деструктор класса TtdSingleLinkList


constructor TtdSingleLinkList.Create(aDispose : TtdDisposeProc);

begin

inherited Create;

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

FDispose :=aDispose;

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

s 11 GetNodeManager;

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

FHead := PslNode (SLNodeManager.AllocNode);

FHead^.slnNext := nil;

FHead^.slnData := nil;

{установить курсор}

MoveBeforeFirst;

end;

destructor TtdSingleLinkList.Destroy;

begin

{удалить все узлы, включая начальный фиктивный узел}

Clear;

SLNodeManager.FreeNode(FHead);

inherited Destroy;

end;


Особый интерес здесь представляет тот факт, что связный список организован таким образом, что для всех экземпляров класса TtdSingleLinkList создается только один диспетчер узлов. Все экземпляры пользуются одним и тем же диспетчером. Можно было бы запрограммировать, чтобы каждый класс создавал свой диспетчер, но это бы означало использование большого дополнительного объема для экземпляра класса. Таким образом, учитывая то, что в приложении, в котором имеется один связный список, как правило, есть несколько списков, было решено ввести переменную класса. Но во всех этих рассуждениях присутствует один недостаток: Delphi не поддерживает переменные класса. Поэтому в коде мы имитируем такую переменную, объявив ее как глобальную в разделе implementation модуля. Если вы просмотрите содержимое файла TDLnkLst.pas, то найдете следующее объявление:


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);

end;


procedure TtdSingleLinkList.MoveBeforeFirst;

begin

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

FCursor := FHead;

FParent := nil;

FCursorIx := -1;

end;


procedure TtdSingleLinkList.MoveNext;

begin

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

if (FCursor <> nil) then begin

FParent := FCursor;

FCursor := FCursor^.slnNext;

inc(FCursorIx);

end;

end;


Вы, возможно, обратили внимание, что некоторые из приведенных методов пользуются полем объекта FCursorIx. Именно это поле позволяет обеспечить высокую эффективность методов, основанных на использовании индекса, поскольку в нем хранится индекс курсора (при этом первый узел имеет индекс 0, точно так же как в TList). Значение поля используется методом ellPositionAtNth, который оптимальным образом перемещает курсор в позицию с указанным индексом.


Джулиан Бакнелл читать все книги автора по порядку

Джулиан Бакнелл - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mybooks.club.


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

Отзывы читателей о книге Фундаментальные алгоритмы и структуры данных в Delphi, автор: Джулиан Бакнелл. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.