2019-08-02 10:17:49 +03:00
|
|
|
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
2017-05-30 20:25:14 +03:00
|
|
|
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Модуль содержит шаблоны классов
|
|
|
|
|
|
/// Stack — стек
|
|
|
|
|
|
/// Queue — очередь
|
|
|
|
|
|
/// DynArray — динамический массив
|
|
|
|
|
|
/// SimpleSet — простое множество на основе динамического массива
|
|
|
|
|
|
/// AssocArray — простой ассоциативный массив на основе динамического массива пар
|
|
|
|
|
|
/// LinkedList — двусвязный список
|
2015-05-14 22:35:07 +03:00
|
|
|
|
unit Collections;
|
|
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- SingleNode ---------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Узел с одним полем связи
|
2015-05-14 22:35:07 +03:00
|
|
|
|
SingleNode<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Значение, содержащееся в узле
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fData: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ссылка на следующий элемент
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fNext: SingleNode<T>;
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Конструктор
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="pData">Значение в узле</param>
|
|
|
|
|
|
/// <param name="pNext">Ссылка на следующий элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
public
|
|
|
|
|
|
constructor Create(pData: T; pNext: SingleNode<T>);
|
|
|
|
|
|
begin
|
|
|
|
|
|
fData := pData;
|
|
|
|
|
|
fNext := pNext;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
property Data: T read fData write fData;
|
|
|
|
|
|
property Next: SingleNode<T> read fNext write fNext;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------- Stack -----------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Шаблон класса Stack
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Stack<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Вершина стека
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fTop: SingleNode<T> := nil;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает пустой стек
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Кладет элемент на вершину стека
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Новый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Push(x: T);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает значение элемента на вершине, снимая его со стека
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Pop: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает значение элемента на вершине стека, не снимая его
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Top: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает истину, если стек пуст
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function IsEmpty: boolean;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое стека в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое стека на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое стека на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------- Queue -----------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Шаблон класса Queue
|
2015-05-14 22:35:07 +03:00
|
|
|
|
Queue<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Голова очереди
|
2015-05-14 22:35:07 +03:00
|
|
|
|
head: SingleNode<T>;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Хвост очереди
|
2015-05-14 22:35:07 +03:00
|
|
|
|
tail: SingleNode<T>;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает пустую очередь
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент в хвост очереди
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Enqueue(x: T);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает значение элемента в голове, удаляя его из очереди
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Dequeue: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает значение элемента в голове очереди, не удаляя его
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Top: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает истину, если очередь пуста
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function IsEmpty: boolean;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое очереди в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое очереди на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое очереди на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------- DynArray ----------------------------------
|
|
|
|
|
|
const
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Минимальная емкость, устанавливаемая при создании массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
MIN_CAP = 4;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Коэффициент увеличения емкости массива при её нехватке
|
2015-05-14 22:35:07 +03:00
|
|
|
|
INC_CAP_FACTOR = 2;
|
|
|
|
|
|
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Шаблон класса DynArray [Динамический массив с автоконтролем памяти]
|
2015-05-14 22:35:07 +03:00
|
|
|
|
DynArray<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Встроенный динамический массив, содержащий данные
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fData: array of T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Размер массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fSize: integer;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Емкость массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fCap: integer;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Устанавливает элемент с индексом ind равным x
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure SetElem(index: integer; x: T);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает элемент массива с индексом ind
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function GetElem(index: integer): T;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает массив размера 0
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает массив размера size
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create(psize: integer);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выделяет новую память. Емкость увеличивается.
|
|
|
|
|
|
/// (Если newCap меньше текущей емкости, ничего не происходит)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="newCap">Новая емкость массива</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Reserve(newCap: integer);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Устанавливает новый размер массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="newSize">Новый размер массива</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Resize(newSize: integer);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент в конец массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Add(x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Вставляет элемент в указанную позицию
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="pos">Позиция, в которую вставляется элемент</param>
|
|
|
|
|
|
/// <param name="x">Вставляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Insert(pos: integer; x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Удаляет элемент массива из указанной позиции
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="pos">Позиция, из которой удаляется элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Remove(pos: integer);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает индекс первого элемента массива равного искомому
|
|
|
|
|
|
/// или -1, если такого элемента нет
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Искомый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Find(x: T): integer;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Количество элементов (размер) массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Count: integer read fSize write Resize;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Емкость массива
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Capacity: integer read fCap write Reserve;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Позволяет обращаться к элементам массива по индексу
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Elem[index: integer]: T read GetElem write SetElem; default;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое массива в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое массива на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое массива на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- SimpleSet ----------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Шаблон класса SimpleSet
|
2015-05-14 22:35:07 +03:00
|
|
|
|
SimpleSet<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Элементы множества
|
2015-05-14 22:35:07 +03:00
|
|
|
|
data: DynArray<T>;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает множество
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент во множество, если его там еще нет
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Add(x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Удаляет элемент из множества, если он там есть
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Удаляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Remove(x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает истину, если множество содержит элемент
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Искомый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function Contains(x: T): boolean;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое массива в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое массива на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое множества на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- AssocArray ---------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Шаблон класса AssocArray
|
2015-05-14 22:35:07 +03:00
|
|
|
|
AssocArray<KeyType, ValueType> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ключи
|
2015-05-14 22:35:07 +03:00
|
|
|
|
keys: DynArray<KeyType>;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Значения, соответствующие ключам
|
2015-05-14 22:35:07 +03:00
|
|
|
|
values: DynArray<ValueType>;
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Устанавливает значение элемента с ключом key равным value
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure SetElem(key: KeyType; value: ValueType);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Возвращает значение элемента с ключом key
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function GetElem(key: KeyType): ValueType;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает ассоциативный массив
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Позволяет обращаться к элементам массива по ключу
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Elem[key: KeyType]: ValueType read GetElem write SetElem; default;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое ассоциативного массива в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое ассоциативного массива на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое ассоциативного массива на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------- LinkedListNode --------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Узел с двумя полями связи
|
2015-05-14 22:35:07 +03:00
|
|
|
|
LinkedListNode<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Значение, содержащееся в узле
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fData: T;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ссылка на предыдущий элемент
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fPrev: LinkedListNode<T>;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ссылка на следующий элемент
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fNext: LinkedListNode<T>;
|
|
|
|
|
|
public
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает новый узел
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="T">Значение узла</param>
|
|
|
|
|
|
/// <param name="Prev">Ссылка на предыдущий элемент</param>
|
|
|
|
|
|
/// <param name="Next">Ссылка на следующий элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create(data: T; prev, next: LinkedListNode<T>);
|
|
|
|
|
|
begin
|
|
|
|
|
|
fData := data;
|
|
|
|
|
|
fNext := next;
|
|
|
|
|
|
fPrev := prev;
|
|
|
|
|
|
end;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Значение, содержащееся в узле
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Value: T read fData write fData;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ссылка на предыдущий элемент — только на чтение
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Prev: LinkedListNode<T> read fPrev;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Ссылка на следующий элемент — только на чтение
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Next: LinkedListNode<T> read fNext;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- LinkedList ---------------------------------
|
|
|
|
|
|
type
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Двусвязный линейный список
|
2015-05-14 22:35:07 +03:00
|
|
|
|
LinkedList<T> = class
|
|
|
|
|
|
private
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Первый элемент (голова)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fFirst: LinkedListNode<T>;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Последний элемент (хвост)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fLast: LinkedListNode<T>;
|
|
|
|
|
|
public
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Создает пустой список
|
2015-05-14 22:35:07 +03:00
|
|
|
|
constructor Create;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Первый элемент (голова) — только на чтение
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property First: LinkedListNode<T> read fFirst;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Последний элемент (хвост) — только на чтение
|
2015-05-14 22:35:07 +03:00
|
|
|
|
property Last: LinkedListNode<T> read fLast;
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент x в начало списка
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure AddFirst(x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент x в конец списка
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure AddLast(x: T);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Удаляет первый элемент списка
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure RemoveFirst();
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Удаляет последний элемент списка
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure RemoveLast();
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент x перед node
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="node">Ссылка на элемент, перед которым нужно добавить новый</param>
|
|
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure AddBefore(node: LinkedListNode<T>; x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Добавляет элемент x после node
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="node">Ссылка на элемент, после которого нужно добавить новый</param>
|
|
|
|
|
|
/// <param name="x">Добавляемый элемент</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure AddAfter(node: LinkedListNode<T>; x: T);
|
|
|
|
|
|
/// <summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Удаляет элемент node
|
2015-05-14 22:35:07 +03:00
|
|
|
|
/// </summary>
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// <param name="node">Ссылка на элемент, который нужно удалить</param>
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Remove(node: LinkedListNode<T>);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Преобразует содержимое списка в строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function ToString: string; override;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое списка на консоль
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Print;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
/// Выводит содержимое списка на консоль с переходом на новую строку
|
2015-05-14 22:35:07 +03:00
|
|
|
|
procedure Println;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
//Сообщения исключений
|
2015-05-14 22:35:07 +03:00
|
|
|
|
const
|
2015-12-28 14:25:15 +03:00
|
|
|
|
PopNilStackExceptionMessage = 'Попытка снятия элемента с пустого стека';
|
|
|
|
|
|
TopNilStackExceptionMessage = 'Попытка получения элемента с пустого стека';
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
DequeueNilQueueExceptionMessage = 'Попытка удаления элемента из пустой очереди';
|
|
|
|
|
|
TopNilQueueExceptionMessage = 'Попытка получения элемента из пустой очереди';
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
NegativeArraySizeExceptionMessage = 'Попытка присвоить размеру массива отрицательное значение ';
|
|
|
|
|
|
InsOutOfArrayBoundExceptionMessage = 'Попытка вставки за границей массива в позицию ';
|
|
|
|
|
|
RemOutOfArrayBoundExceptionMessage = 'Попытка удаления за границей массива из позиции ';
|
|
|
|
|
|
SetElemOutOfBoundExceptionMessage = 'Попытка присвоить значение элементу за границей массива с индексом ';
|
|
|
|
|
|
GetElemOutOfBoundExceptionMessage = 'Попытка получить значение элемента за границей массива с индексом ';
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
RemoveFromNilListExceptionMessage = 'Попытка удаления из пустого списка';
|
|
|
|
|
|
AddNilNodeExceptionMessage = 'Параметр node является нулевой ссылкой';
|
|
|
|
|
|
RemoveNilNodeExceptionMessage = 'Параметр node является нулевой ссылкой';
|
2015-05-14 22:35:07 +03:00
|
|
|
|
|
|
|
|
|
|
// ----------------------------------- Stack -----------------------------------
|
|
|
|
|
|
constructor Stack<T>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
fTop := nil;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Stack<T>.Push(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
fTop := new SingleNode<T>(x, fTop);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Stack<T>.Pop: T;
|
|
|
|
|
|
begin
|
|
|
|
|
|
if IsEmpty then
|
|
|
|
|
|
raise new Exception(PopNilStackExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
Result := fTop.data;
|
|
|
|
|
|
fTop := fTop.next;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Stack<T>.Top: T;
|
|
|
|
|
|
begin
|
|
|
|
|
|
if IsEmpty then
|
|
|
|
|
|
raise new Exception(TopNilStackExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
Result := fTop.data;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Stack<T>.IsEmpty: boolean;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := (fTop = nil);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Stack<T>.ToString: string;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := '';
|
|
|
|
|
|
var curElem := fTop;
|
|
|
|
|
|
while curElem <> nil do
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result += curElem.data.ToString + ' ';
|
|
|
|
|
|
curElem := curElem.next;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Stack<T>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Stack<T>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------- Queue -----------------------------------
|
|
|
|
|
|
constructor Queue<T>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
head := nil;
|
|
|
|
|
|
tail := nil;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Queue<T>.Enqueue(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if IsEmpty then
|
|
|
|
|
|
begin
|
|
|
|
|
|
head := new SingleNode<T>(x, nil);
|
|
|
|
|
|
tail := head;
|
|
|
|
|
|
end
|
|
|
|
|
|
else
|
|
|
|
|
|
begin
|
|
|
|
|
|
tail.next := new SingleNode<T>(x, nil);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
tail := tail.next; // элемент удаляется из хвоста очереди (т.е. хвостом становится следующий элемент)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Queue<T>.Dequeue: T;
|
|
|
|
|
|
begin
|
|
|
|
|
|
if IsEmpty then
|
|
|
|
|
|
raise new Exception(DequeueNilQueueExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
Result := head.data;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
head := head.next; // элемент удаляется из головы очереди (т.е. головой становится следующий элемент)
|
2015-05-14 22:35:07 +03:00
|
|
|
|
if head = nil then
|
|
|
|
|
|
tail := nil;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Queue<T>.Top: T;
|
|
|
|
|
|
begin
|
|
|
|
|
|
if IsEmpty then
|
|
|
|
|
|
raise new Exception(TopNilQueueExceptionMessage);
|
|
|
|
|
|
Result := head.data;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Queue<T>.IsEmpty: boolean;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := (head = nil);
|
|
|
|
|
|
if Result then
|
|
|
|
|
|
Assert(tail = nil);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function Queue<T>.ToString: string;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := '';
|
|
|
|
|
|
var curElem := head;
|
|
|
|
|
|
while curElem <> nil do
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result += curElem.data + ' ';
|
|
|
|
|
|
curElem := curElem.next;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Queue<T>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure Queue<T>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------- DynArray ---------------------------------
|
|
|
|
|
|
constructor DynArray<T>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Create(0);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
constructor DynArray<T>.Create(pSize: integer);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if pSize < 0 then
|
|
|
|
|
|
raise new Exception(NegativeArraySizeExceptionMessage + pSize.ToString);
|
|
|
|
|
|
|
|
|
|
|
|
fSize := pSize;
|
2015-12-28 14:25:15 +03:00
|
|
|
|
fCap := INC_CAP_FACTOR * pSize + MIN_CAP; // Устанавливаем емкость "с запасом"
|
2015-05-14 22:35:07 +03:00
|
|
|
|
SetLength(fData, fCap);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Reserve(newCap: integer);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if newCap > fCap then
|
|
|
|
|
|
begin
|
|
|
|
|
|
SetLength(fData, newCap);
|
|
|
|
|
|
fCap := newCap;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Resize(newSize: integer);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if newSize < 0 then
|
|
|
|
|
|
raise new Exception(NegativeArraySizeExceptionMessage + newSize.ToString);
|
|
|
|
|
|
|
|
|
|
|
|
if newSize > fCap then
|
|
|
|
|
|
begin
|
|
|
|
|
|
Reserve(INC_CAP_FACTOR * newSize);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
for var i := fSize to newSize - 1 do // явным образом заполняем новые элементы
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fData[i] := default(T);
|
|
|
|
|
|
end;
|
|
|
|
|
|
fSize := newSize;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Add(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
Resize(fSize + 1);
|
|
|
|
|
|
fData[fSize - 1] := x;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Insert(pos: integer; x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if (pos < 0) or (pos > fSize - 1) then
|
|
|
|
|
|
raise new Exception(InsOutOfArrayBoundExceptionMessage + pos.ToString);
|
|
|
|
|
|
|
|
|
|
|
|
Resize(fSize + 1);
|
|
|
|
|
|
for var i := fSize - 2 downto pos do
|
|
|
|
|
|
fData[i + 1] := fData[i];
|
|
|
|
|
|
fData[pos] := x;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Remove(pos: integer);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if (pos < 0) or (pos > fSize - 1) then
|
|
|
|
|
|
raise new Exception(RemOutOfArrayBoundExceptionMessage + pos.ToString);
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
for var i := pos to fSize - 2 do // сдвиг элементов влево на 1, начиная с позиции pos
|
2015-05-14 22:35:07 +03:00
|
|
|
|
fData[i] := fData[i + 1];
|
|
|
|
|
|
Resize(fSize - 1);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function DynArray<T>.Find(x: T): integer;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := -1;
|
|
|
|
|
|
for var i := 0 to fSize - 1 do
|
|
|
|
|
|
if fData[i] = x then
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := i;
|
|
|
|
|
|
exit;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.SetElem(index: integer; x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if (index < 0) or (index > fSize - 1) then
|
|
|
|
|
|
raise new Exception(SetElemOutOfBoundExceptionMessage + index.ToString);
|
|
|
|
|
|
|
|
|
|
|
|
fData[index] := x;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
2015-12-28 14:25:15 +03:00
|
|
|
|
{Возвращает элемент массива с индексом ind}
|
2015-05-14 22:35:07 +03:00
|
|
|
|
function DynArray<T>.GetElem(index: integer): T;
|
|
|
|
|
|
begin
|
|
|
|
|
|
if (index < 0) or (index > fSize - 1) then
|
|
|
|
|
|
raise new Exception(GetElemOutOfBoundExceptionMessage + index.ToString);
|
|
|
|
|
|
|
|
|
|
|
|
Result := fData[index];
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function DynArray<T>.ToString: string;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := '';
|
|
|
|
|
|
for var i := 0 to fSize - 1 do
|
|
|
|
|
|
Result += fData[i].ToString + ' ';
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure DynArray<T>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- SimpleSet ----------------------------------
|
|
|
|
|
|
constructor SimpleSet<T>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
data := new DynArray<T>;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure SimpleSet<T>.Add(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if data.Find(x) = -1 then
|
|
|
|
|
|
data.Add(x);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure SimpleSet<T>.Remove(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
var xPos := data.Find(x);
|
|
|
|
|
|
if xPos <> -1 then
|
|
|
|
|
|
data.Remove(xPos);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function SimpleSet<T>.Contains(x: T): boolean;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := (data.Find(x) <> -1);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function SimpleSet<T>.ToString: string;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := data.ToString;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure SimpleSet<T>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure SimpleSet<T>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- AssocArray ---------------------------------
|
|
|
|
|
|
constructor AssocArray<KeyType, ValueType>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
keys := new DynArray<KeyType>;
|
|
|
|
|
|
values := new DynArray<ValueType>;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure AssocArray<KeyType, ValueType>.SetElem(key: KeyType; value: ValueType);
|
|
|
|
|
|
begin
|
|
|
|
|
|
var ind := Keys.Find(key);
|
|
|
|
|
|
if ind <> -1 then
|
|
|
|
|
|
Values[ind] := value
|
|
|
|
|
|
else
|
|
|
|
|
|
begin
|
|
|
|
|
|
Keys.Add(key);
|
|
|
|
|
|
Values.Add(value);
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function AssocArray<KeyType, ValueType>.GetElem(key: KeyType): ValueType;
|
|
|
|
|
|
begin
|
|
|
|
|
|
var ind := Keys.Find(key);
|
|
|
|
|
|
if ind <> -1 then
|
|
|
|
|
|
Result := Values[ind]
|
|
|
|
|
|
else Result := default(ValueType);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function AssocArray<KeyType, ValueType>.ToString: string;
|
|
|
|
|
|
const
|
|
|
|
|
|
NewLine = #13#10;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := '';
|
|
|
|
|
|
for var i := 0 to keys.Count - 1 do
|
|
|
|
|
|
Result += keys[i].ToString + ' ' + values[i].ToString + NewLine;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure AssocArray<KeyType, ValueType>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure AssocArray<KeyType, ValueType>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------- LinkedList ---------------------------------
|
|
|
|
|
|
constructor LinkedList<T>.Create;
|
|
|
|
|
|
begin
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.AddFirst(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
var val := new LinkedListNode<T>(x, nil, fFirst);
|
|
|
|
|
|
if fFirst <> nil then
|
|
|
|
|
|
fFirst.fPrev := val;
|
|
|
|
|
|
|
|
|
|
|
|
fFirst := val;
|
|
|
|
|
|
if fLast = nil then
|
|
|
|
|
|
fLast := fFirst;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.AddLast(x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
var val := new LinkedListNode<T>(x, fLast, nil);
|
|
|
|
|
|
if fLast <> nil then
|
|
|
|
|
|
fLast.fNext := val;
|
|
|
|
|
|
|
|
|
|
|
|
fLast := val;
|
|
|
|
|
|
if fFirst = nil then
|
|
|
|
|
|
fFirst := fLast;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.RemoveFirst();
|
|
|
|
|
|
begin
|
|
|
|
|
|
if fFirst = nil then
|
|
|
|
|
|
raise new Exception(RemoveFromNilListExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
fFirst := fFirst.fNext;
|
|
|
|
|
|
if fFirst = nil then
|
|
|
|
|
|
fLast := nil
|
|
|
|
|
|
else
|
|
|
|
|
|
fFirst.fPrev := nil;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.RemoveLast();
|
|
|
|
|
|
begin
|
|
|
|
|
|
if fLast = nil then
|
|
|
|
|
|
raise new Exception(RemoveFromNilListExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
fLast := fLast.fPrev;
|
|
|
|
|
|
if fLast = nil then
|
|
|
|
|
|
fFirst := nil
|
|
|
|
|
|
else
|
|
|
|
|
|
fLast.fNext := nil;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.AddBefore(node: LinkedListNode<T>; x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if node = nil then
|
|
|
|
|
|
raise new Exception(AddNilNodeExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
if node = fFirst then
|
|
|
|
|
|
AddFirst(x)
|
|
|
|
|
|
else
|
|
|
|
|
|
begin
|
|
|
|
|
|
var val := new LinkedListNode<T>(x, node.fPrev, node);
|
|
|
|
|
|
node.fPrev.fNext := val;
|
|
|
|
|
|
node.fPrev := val;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.AddAfter(node: LinkedListNode<T>; x: T);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if node = nil then
|
|
|
|
|
|
raise new Exception(AddNilNodeExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
if node = fLast then
|
|
|
|
|
|
AddLast(x)
|
|
|
|
|
|
else
|
|
|
|
|
|
begin
|
|
|
|
|
|
var val := new LinkedListNode<T>(x, node, node.fNext);
|
|
|
|
|
|
node.fNext.fPrev := val;
|
|
|
|
|
|
node.fNext := val;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.Remove(node: LinkedListNode<T>);
|
|
|
|
|
|
begin
|
|
|
|
|
|
if node = nil then
|
|
|
|
|
|
raise new Exception(RemoveNilNodeExceptionMessage);
|
|
|
|
|
|
|
|
|
|
|
|
if node = fFirst then
|
|
|
|
|
|
RemoveFirst
|
|
|
|
|
|
else if node = fLast then
|
|
|
|
|
|
RemoveLast
|
|
|
|
|
|
else
|
|
|
|
|
|
begin
|
|
|
|
|
|
node.fPrev.fNext := node.fNext;
|
|
|
|
|
|
node.fNext.fPrev := node.fPrev;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
function LinkedList<T>.ToString: string;
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := '';
|
|
|
|
|
|
var cur := fFirst;
|
|
|
|
|
|
while cur <> nil do
|
|
|
|
|
|
begin
|
|
|
|
|
|
Result := cur.Value.ToString + ' ';
|
|
|
|
|
|
cur := cur.Next;
|
|
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.Print;
|
|
|
|
|
|
begin
|
|
|
|
|
|
write(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure LinkedList<T>.Println;
|
|
|
|
|
|
begin
|
|
|
|
|
|
writeln(ToString);
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
end.
|