Collections — различия между версиями

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Collections)
Строка 70: Строка 70:
 
   prev := pPrev;
 
   prev := pPrev;
 
end;
 
end;
 
end.
 
</source>
 
 
== Составляющие классы ==
 
=== Stack ===
 
<xh4> Интерфейс </xh4>
 
'''Create'''
 
  Создает пустой стек
 
 
'''Create(params xDatas: array of DataType)'''
 
  Создает стек, заполненный элементами, переданными в качестве параметров
 
 
 
'''Push(x: DataType)'''
 
  Кладет элемент x на вершину стека
 
 
'''Pop: DataType'''
 
  Возвращает элемент типа DataType, снимая его с вершины стека
 
   
 
'''Top: DataType'''
 
  Возвращает значение элемента на вершине стека
 
 
'''IsEmpty: boolean;'''
 
  Возвращает истину, если стек пуст
 
       
 
'''Print(delim: string; elemsInLine: integer)'''
 
  Выводит подряд содержимое стека
 
  (''delim'' — разделитель между элементами в строке,
 
  ''elemsInLine'' — количество элементов, выводимых в одной строке)
 
   
 
'''Println'''
 
  Выводит содержимое стека в каждой строке
 
 
<xh4> Реализация </xh4>
 
<source lang="Delphi">
 
/// Модуль содержит шаблон класса
 
///  Stack — стек
 
unit StackUnit;
 
 
interface
 
 
 
uses Nodes;  // для использования типа SingleNode<DataType> —
 
              // узла с одним полем связи
 
             
 
const
 
  /// Ширина поля вывода
 
  PRINT_FIELD_WIDTH = 5;
 
  /// Разделитель при выводе элементов
 
  DELIMETR = '  ';
 
  /// Количество элементов, выводимых в одной строке при выводе
 
  ELEMS_IN_LINE = 5;
 
 
  /// Сообщение о пустоте стека
 
  EMPTY_STACK = 'Стек пуст';
 
 
type
 
  /// Шаблон класса Stack [Стек]
 
  Stack<DataType> = class
 
  private
 
    /// Вершина стека
 
    fTop: SingleNode<DataType> := nil;  // field Top
 
   
 
  public
 
// ---------------------------- Стандартные методы ---------------------------
 
    /// Создает пустой стек
 
    constructor Create;
 
    /// Создает стек, заполненный элементами, переданными в качестве параметров
 
    constructor Create(params xDatas: array of DataType);
 
 
    /// Кладет элемент x на вершину стека
 
    procedure Push(x: DataType);
 
    /// Возвращает элемент типа DataType, снимая его с вершины стека
 
    function Pop: DataType;
 
    /// Возвращает значение элемента на вершине стека
 
    function Top: DataType;
 
   
 
    /// Возвращает истину, если стек пуст
 
    function IsEmpty: boolean;   
 
// ----------------------------- Вывод содержимого ---------------------------
 
    /// <summary>
 
    /// Выводит подряд содержимое стека
 
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
    procedure Print(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое стека в каждой строке
 
    procedure Println;
 
  end;
 
 
 
 
 
// ================================================================= IMPLEMENTATION ===================================================================
 
implementation
 
 
// ---------------------------- Стандартные методы ---------------------------
 
{Стандартный конструктор}
 
constructor Stack<DataType>.Create;
 
begin
 
  fTop := nil;
 
end;
 
{Создает стек, заполненный элементами, переданными в качестве параметров}
 
constructor Stack<DataType>.Create(params xDatas: array of DataType);
 
begin
 
  fTop := nil;
 
  for var i := 0 to xDatas.Length - 1 do
 
    Push(xDatas[i]);
 
end;
 
 
{Кладет элемент x на вершину стека}
 
procedure Stack<DataType>.Push(x: DataType);
 
begin
 
  fTop := new SingleNode<DataType>(x, fTop);
 
end;
 
 
{Возвращает элемент типа DataType, снимая его с вершины стека}
 
function Stack<DataType>.Pop: DataType;
 
begin
 
  Assert(not IsEmpty);
 
  result := fTop.data;
 
  fTop := fTop.next;  // элемент снимается с вершины стека
 
                      // (т.е. вершиной становится следующий элемент)
 
end;
 
 
{Возвращает значение элемента на вершине стека}
 
function Stack<DataType>.Top: DataType;
 
begin
 
  Assert(not IsEmpty);
 
  result := fTop.data;
 
end;
 
 
{Возвращает истину, если стек пуст}
 
function Stack<DataType>.IsEmpty: boolean;
 
begin
 
  result := (fTop = nil);
 
end;
 
 
// ----------------------------- Вывод содержимого ---------------------------
 
{Выводит подряд содержимое стека
 
    delim — разделитель между элементами в строке
 
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure Stack<DataType>.Print(delim: string; elemsInLine: integer);
 
begin
 
  if IsEmpty then
 
    writeln(EMPTY_STACK)
 
  else
 
  begin
 
    var elemsInd := 1;  // индекс элемента стека
 
                        // нужен для вывода по строкам
 
    var curElem := fTop;
 
    while curElem <> nil do
 
    begin
 
      if (elemsInd mod elemsInLine) <> 0 then
 
        write(curElem.data:PRINT_FIELD_WIDTH, delim)
 
      else              // вывели требуемое количество элементов в строке
 
        writeln(curElem.data:PRINT_FIELD_WIDTH, delim);
 
 
      curElem := curElem.next;
 
      elemsInd += 1;
 
    end;
 
  end;
 
end;
 
 
{Выводит содержимое стека в каждой строке}
 
procedure Stack<DataType>.Println;
 
begin
 
  if IsEmpty then
 
    writeln(EMPTY_STACK)
 
  else
 
  begin
 
    var curElem := fTop;
 
    while curElem <> nil do
 
    begin
 
      writeln(curElem.data:PRINT_FIELD_WIDTH);
 
      curElem := curElem.next;;
 
    end;
 
  end;
 
end;
 
 
 
end.
 
</source>
 
 
=== Queue ===
 
<xh4> Интерфейс </xh4>   
 
 
'''Create'''
 
  Создает пустую очередь
 
 
'''Create(params xDatas: array of DataType)'''
 
  Создает очередь, заполненную элементами, переданными в качестве параметров
 
 
 
'''Enqueue(x: DataType)'''
 
  Добавляет элемент x в хвост очереди
 
 
'''Dequeue: DataType'''
 
  Возвращает элемент типа DataType, убирая его из головы очереди
 
   
 
'''IsEmpty: boolean;'''
 
  Возвращает истину, если очередь пуста
 
       
 
'''Print(delim: string; elemsInLine: integer)'''
 
  Выводит подряд содержимое очереди от головы к хвосту
 
  (''delim'' — разделитель между элементами в строке,
 
  ''elemsInLine'' — количество элементов, выводимых в одной строке)
 
   
 
'''Println'''
 
  Выводит содержимое очереди от головы к хвосту в каждой строке
 
 
<xh4> Реализация </xh4>
 
<source lang="Delphi">
 
/// Модуль содержит шаблон класса
 
///  Queue — очередь
 
unit QueueUnit;
 
 
interface
 
 
uses Nodes;  // для использования типа SingleNode<DataType> —
 
              // узла с одним полем связи
 
 
 
const
 
  /// Ширина поля вывода
 
  PRINT_FIELD_WIDTH = 5;
 
  /// Разделитель при выводе элементов
 
  DELIMETR = '  ';
 
  /// Количество элементов, выводимых в одной строке при выводе
 
  ELEMS_IN_LINE = 5;
 
 
 
  /// Сообщение о пустоте очереди
 
  EMPTY_QUEUE = 'Очередь пуста';
 
 
type 
 
  /// Шаблон класса Queue [Очередь]
 
  Queue<DataType> = class
 
  private
 
    /// Голова очереди
 
    head: SingleNode<DataType>;
 
    /// Хвост очереди
 
    tail: SingleNode<DataType>;
 
   
 
  public
 
// ---------------------------- Стандартные методы ---------------------------
 
    /// Создает пустую очередь
 
    constructor Create;
 
    /// Создает очередь, заполненную элементами, переданными в качестве параметров
 
    constructor Create(params xDatas: array of DataType);
 
   
 
    /// Добавляет элемент x в хвост очереди
 
    procedure Enqueue(x: DataType);
 
    /// Возвращает элемент типа DataType, убирая его из головы очереди
 
    function Dequeue: DataType;
 
    /// Возвращает истину, если очередь пуста
 
   
 
    function IsEmpty: boolean;
 
// ----------------------------- Вывод содержимого ---------------------------
 
    /// <summary>
 
    /// Выводит подряд содержимое очереди от головы к хвосту
 
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
    procedure Print(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое очереди от головы к хвосту в каждой строке
 
    procedure Println;
 
  end;
 
 
 
// ================================================================= IMPLEMENTATION ===================================================================
 
implementation
 
 
// ---------------------------- Стандартные методы ---------------------------
 
{Создает пустую очередь}
 
constructor Queue<DataType>.Create;
 
begin
 
  head := nil;
 
  tail := nil;
 
end;
 
{Создает очередь, заполненную элементами, переданными в качестве параметров}
 
constructor Queue<DataType>.Create(params xDatas: array of DataType);
 
begin
 
  head := nil;
 
  tail := nil;
 
  for var i := 0 to xDatas.Length - 1 do
 
    Enqueue(xDatas[i]);
 
end;
 
 
{Добавляет элемент x в хвост очереди}
 
procedure Queue<DataType>.Enqueue(x: DataType);
 
begin
 
  if IsEmpty then
 
  begin
 
    head := new SingleNode<DataType>(x, nil);
 
    tail := head;
 
  end
 
  else  // if not IsEmpty
 
  begin
 
    tail.next := new SingleNode<DataType>(x, nil);
 
    tail := tail.next;  // элемент убирается из хвоста очереди
 
                        // (т.е. хвостом становится следующий элемент)
 
  end;
 
end;
 
 
{Возвращает элемент типа DataType, убирая его из головы очереди}
 
function Queue<DataType>.Dequeue: DataType;
 
begin
 
  Assert(not IsEmpty);
 
  result := head.data;
 
 
  head := head.next;  // элемент убирается из головы очереди
 
                      // (т.е. головой становится следующий элемент)
 
  if head = nil then
 
    tail := nil;
 
end;
 
 
{Возвращает истину, если очередь пуста}
 
function Queue<DataType>.IsEmpty: boolean;
 
begin
 
  result := (head = nil);
 
  if result then
 
    Assert(tail = nil);
 
end;
 
 
// ----------------------------- Вывод содержимого ---------------------------
 
{Выводит подряд содержимое очереди от головы к хвосту
 
    delim — разделитель между элементами в строке
 
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure Queue<DataType>.Print(delim: string; elemsInLine: integer);
 
begin
 
  if IsEmpty then
 
    writeln(EMPTY_QUEUE)
 
  else
 
  begin
 
    var elemsInd := 1;  // индекс элемента стека
 
                        // нужен для вывода по строкам
 
    var curElem := head;
 
    while curElem <> nil do
 
    begin
 
      if (elemsInd mod elemsInLine) <> 0 then
 
        write(curElem.data:PRINT_FIELD_WIDTH, delim)
 
      else              // вывели требуемое количество элементов в строке
 
        writeln(curElem.data:PRINT_FIELD_WIDTH, delim);
 
       
 
      curElem := curElem.next;
 
      elemsInd += 1;
 
    end;
 
  end;
 
end;
 
 
{Выводит содержимое очереди от головы к хвосту в каждой строке}
 
procedure Queue<DataType>.Println;
 
begin
 
  if IsEmpty then
 
    writeln(EMPTY_QUEUE)
 
  else
 
  begin
 
    var curElem := head;
 
    while curElem <> nil do
 
    begin
 
      writeln(curElem.data:PRINT_FIELD_WIDTH);
 
      curElem := curElem.next;;
 
    end;
 
  end;
 
end;
 
 
 
end.
 
</source>
 
 
=== DynArray ===
 
<xh4> Интерфейс </xh4>
 
'''Count'''
 
  Количество элементов (размер) массива
 
 
'''Capacity'''
 
  Емкость массива (отведенная память)
 
 
 
'''Create(pSize: integer)'''
 
  Создает массив размера pSize
 
 
'''Create(params xDatas: array of DataType)'''
 
  Создает массив, заполненный элементами, переданными в качестве параметров
 
 
'''Reserve(newCap: integer)'''
 
  Выделяет новую память. Емкость увеличивается до newCap
 
  (Если newCap меньше текущей емкости, ничего не происходит)
 
 
'''Resize(newSize: integer)'''
 
  Устанавливает размер массива равным newSize
 
 
'''Add(params xDatas: array of DataType)'''
 
  Добавляет элементы, переданные в качестве параметров, в конец массива
 
 
'''Insert(pos: integer; params xDatas: array of DataType)'''
 
  Вставляет в массив элементы, переданные в качестве параметров,
 
  начиная с позиции pos
 
 
'''Delete(pos: integer; count: integer)'''
 
  Удаляет count элементов массива, начиная с позиции pos.
 
  (По умолчанию удаляется один элемент)
 
 
'''Find(x: DataType): integer'''
 
  Возвращает индекс первого элемента массива равного x
 
  или -1, если такого элемента нет
 
 
'''Find(x: DataType; from: integer): integer'''
 
  Возвращает индекс элемента массива равного x, начиная с позиции from,
 
  или -1, если такого элемента нет
 
 
'''Print(delim: string; elemsInLine: integer)'''
 
  Выводит содержимое массива в прямом порядке
 
  (''delim'' — разделитель между элементами в строке
 
  ''elemsInLine'' — количество элементов, выводимых в одной строке)
 
 
'''PrintReverse(delim: string; elemsInLine: integer)'''
 
  Выводит содержимое массива в обратном порядке
 
  ''delim'' — разделитель между элементами в строке
 
  ''elemsInLine'' — количество элементов, выводимых в одной строке)
 
 
'''Println'''
 
  Выводит содержимое массива в прямом порядке в каждой строке
 
 
'''PrintlnReverse'''
 
  Выводит содержимое массива в прямом порядке в каждой строке
 
 
<xh4> Реализация </xh4>
 
<source lang="Delphi">
 
/// Модуль содержит шаблон класса
 
///  DynArray — динамический массив с автоконтролем памяти
 
unit DynArrayUnit;
 
 
interface
 
 
const
 
  /// Ширина поля вывода
 
  PRINT_FIELD_WIDTH = 5;
 
  /// Разделитель при выводе элементов
 
  DELIMETR = '  ';
 
  /// Количество элементов, выводимых в одной строке при выводе
 
  ELEMS_IN_LINE = 5;
 
 
 
  /// Минимальная емкость, устанавливаемая при создании массива
 
  MIN_CAP = 4;
 
  /// Коэффициент увеличения емкости массива при её нехватке
 
  INC_CAP_FACTOR = 2;
 
 
 
type
 
  /// Шаблон класса DynArray [Динамический массив с автоконтролем памяти]
 
  DynArray<DataType> = class
 
  private
 
    /// Встроенный динамический массив, содержащий данные
 
    data: array of DataType;
 
    /// Размер массива
 
    size: integer;
 
    /// Емкость массива
 
    cap: integer;
 
   
 
    /// Устанавливает элемент с индексом ind равным x
 
    procedure SetElem(ind: integer; x: DataType);
 
    /// Возвращает элемент массива с индексом ind
 
    function GetElem(ind: integer): DataType;
 
   
 
  public
 
// ---------------------------- Стандартные методы ---------------------------
 
    /// Создает массив размера pSize
 
    constructor Create(pSize: integer := 0);
 
    /// Создает массив, заполненный элементами, переданными в качестве параметров
 
    constructor Create(params xDatas: array of DataType);
 
   
 
    /// Выделяет новую память. Емкость увеличивается до newCap
 
    /// (Если newCap меньше текущей емкости, ничего не происходит)
 
    procedure Reserve(newCap: integer);
 
    /// Устанавливает размер массива равным newSize
 
    procedure Resize(newSize: integer);
 
   
 
    /// Добавляет элементы, переданные в качестве параметров, в конец массива
 
    procedure Add(params xDatas: array of DataType);
 
    /// Вставляет в массив элементы, переданные в качестве параметров,
 
    /// начиная с позиции pos
 
    procedure Insert(pos: integer; params xDatas: array of DataType);
 
    /// Удаляет count элементов массива, начиная с позиции pos.
 
    /// (По умолчанию удаляется один элемент)
 
    procedure Delete(pos: integer; count: integer := 1);
 
   
 
    /// Возвращает индекс первого элемента массива равного x
 
    /// или -1, если такого элемента нет
 
    function Find(x: DataType): integer;
 
    /// Возвращает индекс элемента массива равного x, начиная с позиции from,
 
    /// или -1, если такого элемента нет}
 
    function Find(x: DataType; from: integer): integer;
 
// --------------------------------- Свойства --------------------------------
 
    /// Количество элементов (размер) массива
 
    property Count: integer read size write Resize;
 
    /// Емкость массива (отведенная память)
 
    property Capacity: integer read cap write Reserve;
 
    /// Позволяет обращаться к элементам массива по индексу
 
    /// (например, apples[5])
 
    property Elem[index: integer]: DataType read GetElem write SetElem; default;
 
// ----------------------------- Вывод содержимого ---------------------------
 
    /// <summary>
 
    /// Выводит содержимое массива в прямом порядке
 
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
    procedure Print(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// <summary>
 
    /// Выводит содержимое массива в обратном порядке
 
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
    procedure PrintReverse(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое массива в прямом порядке в каждой строке
 
    procedure Println;
 
    /// Выводит содержимое массива в обратном порядке в каждой строке
 
    procedure PrintlnReverse;
 
  end;
 
 
 
// ================================================================= IMPLEMENTATION ===================================================================
 
implementation
 
 
// ---------------------------- Стандартные методы ---------------------------
 
{Создает массив размера pSize}
 
constructor DynArray<DataType>.Create(pSize: integer);
 
begin
 
  size := pSize;
 
  cap := INC_CAP_FACTOR*pSize + MIN_CAP; // Устанавливаем емкость "с запасом"
 
  SetLength(data, cap);
 
end;
 
{Создает массив, заполненный элементами, переданными в качестве параметров}
 
constructor DynArray<DataType>.Create(params xDatas: array of DataType);
 
begin
 
  Create(xDatas.Length);  // Сначала нужно создать массив требуемого размера
 
 
 
  for var i := 0 to xDatas.Length - 1 do
 
    data[i] := xDatas[i];
 
end;
 
 
{Выделяет новую память. Емкость увеличивается до newCap
 
(Если newCap меньше текущей емкости, ничего не происходит)}
 
procedure DynArray<DataType>.Reserve(newCap: integer);
 
begin
 
  if newCap > cap then
 
  begin
 
    SetLength(data, newCap);
 
    cap := newCap;
 
  end;
 
end;
 
 
{Устанавливает размер массива равным newSize}
 
procedure DynArray<DataType>.Resize(newSize: integer);
 
begin
 
  if newSize <= cap then
 
    size := newSize
 
  else
 
  begin
 
    Reserve(INC_CAP_FACTOR * newSize);
 
    for var i := size to newSize - 1 do // явным образом заполняем новые элементы
 
      data[i] := default(DataType);
 
    size := newSize;
 
  end;
 
end;
 
 
{Добавляет элементы, переданные в качестве параметров, в конец массива}
 
procedure DynArray<DataType>.Add(params xDatas: array of DataType);
 
begin
 
  Resize(size + xDatas.Length);
 
  for var i := 0 to xDatas.Length - 1 do
 
    data[size-xDatas.Length + i] := xDatas[i];
 
end;
 
 
{Вставляет в массив элементы, переданные в качестве параметров,
 
начиная с позиции pos}
 
procedure DynArray<DataType>.Insert(pos: integer; params xDatas: array of DataType);
 
begin
 
  Assert((0 <= pos) and (pos <= size-1));
 
 
 
  Resize(size + xDatas.Length);
 
  for var i := size - 2 downto pos+xDatas.Length - 1 do // сдвиг элементов вправо, начиная с позиции pos
 
    data[i+1] := data[i-xDatas.Length + 1];
 
  for var i := 0 to xDatas.Length - 1 do                // заполнение "освободившихся" элементов новыми значениями
 
    data[pos+i] := xDatas[i];
 
end;
 
 
{Удаляет count элементов массива, начиная с позиции pos.
 
(По умолчанию удаляется один элемент)}
 
procedure DynArray<DataType>.Delete(pos: integer; count: integer);
 
begin
 
  Assert((0 <= pos) and (pos <= size-1));
 
  Assert((0 <= count) and (count <= size));
 
 
 
  if (size - pos) < count then          // если количество удаляемых элементов больше,
 
                                        // чем их осталось до конца массива
 
    count := size - pos;
 
  for var i := pos to size-1 - count do // сдвиг элементов влево на count, начиная с позиции pos
 
    data[i] := data[i + count];
 
  Resize(size - count);                // "отрезание" лишних count элементов
 
end;
 
 
{Возвращает индекс первого элемента массива равного x
 
или -1, если такого элемента нет}
 
function DynArray<DataType>.Find(x: DataType): integer;
 
begin
 
  result := -1;
 
  for var i := 0 to size - 1 do
 
    if data[i] = x then
 
    begin
 
      result := i;
 
      exit;
 
    end;
 
end;
 
{Возвращает индекс элемента массива равного x, начиная с позиции from,
 
или -1, если такого элемента нет}
 
function DynArray<DataType>.Find(x: DataType; from: integer): integer;
 
begin
 
  Assert((0 <= from) and (from <= size-1));
 
 
 
  result := -1;
 
  for var i := from to size - 1 do
 
    if data[i] = x then
 
    begin
 
      result := i;
 
      exit;
 
    end;
 
end;
 
 
// ---------------------------- Доступ к элементам ---------------------------
 
{Устанавливает элемент с индексом ind равным x}
 
procedure DynArray<DataType>.SetElem(ind: integer; x: DataType);
 
begin
 
  Assert((0 <= ind) and (ind <= size-1));
 
  data[ind] := x;
 
end;
 
{Возвращает элемент массива с индексом ind}
 
function DynArray<DataType>.GetElem(ind: integer): DataType;
 
begin
 
  Assert((0 <= ind) and (ind <= size-1));
 
  result := data[ind];
 
end;
 
 
// ----------------------------- Вывод содержимого ---------------------------
 
{Выводит содержимое массива в прямом порядке
 
    delim — разделитель между элементами в строке
 
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure DynArray<DataType>.Print(delim: string; elemsInLine: integer);
 
begin
 
  for var i := 1 to size do
 
    if (i mod elemsInLine) <> 0 then
 
      write(data[i-1]:PRINT_FIELD_WIDTH, delim)
 
    else          // если вывели elemsInLine элементов, переходим на новую строку
 
      writeln(data[i-1]:PRINT_FIELD_WIDTH);
 
end;
 
{Выводит содержимое массива в обратном порядке
 
    delim — разделитель между элементами в строке
 
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure DynArray<DataType>.PrintReverse(delim: string; elemsInLine: integer);
 
begin
 
  for var i := 1 to size do
 
    if (i mod elemsInLine) <> 0 then
 
      write(data[size-i]:PRINT_FIELD_WIDTH, delim)
 
    else          // если вывели elemsInLine элементов, переходим на новую строку
 
      writeln(data[size-i]:PRINT_FIELD_WIDTH);
 
end;
 
 
{Выводит содержимое массива в прямом порядке в каждой строке}
 
procedure DynArray<DataType>.Println;
 
begin
 
  for var i := 0 to size - 1 do
 
    writeln(data[i]);
 
end;
 
{Выводит содержимое массива в обратном порядке в каждой строке}
 
procedure DynArray<DataType>.PrintlnReverse;
 
begin
 
  for var i := size - 1 downto 0 do
 
    writeln(data[i]);
 
end;
 
 
  
 
end.
 
end.
Строка 750: Строка 75:
  
 
== Collections ==
 
== Collections ==
<xh4> Интерфейс </xh4>
+
<!-- <xh4> Интерфейс </xh4>
 
'''''<font size=2>Stack</font>'''''
 
'''''<font size=2>Stack</font>'''''
 
  '''Create'''
 
  '''Create'''
Строка 856: Строка 181:
 
   
 
   
 
  '''PrintlnReverse'''
 
  '''PrintlnReverse'''
   Выводит содержимое массива в прямом порядке в каждой строке
+
   Выводит содержимое массива в прямом порядке в каждой строке -->
  
 
<xh4> Реализация </xh4>
 
<xh4> Реализация </xh4>
Строка 864: Строка 189:
 
///  Queue — очередь
 
///  Queue — очередь
 
///  DynArray — динамический массив с автоконтролем памяти
 
///  DynArray — динамический массив с автоконтролем памяти
 +
///  SimpleSet — простое множество (с минимальным набором операций)
 +
///  AssocArray — ассоциативный массив
 
unit Collections;
 
unit Collections;
 
 
   
 
   
 
interface
 
interface
Строка 871: Строка 197:
 
uses Nodes;  // для использования типа SingleNode<DataType> —  
 
uses Nodes;  // для использования типа SingleNode<DataType> —  
 
               // узла с одним полем связи
 
               // узла с одним полем связи
 +
 
 
   
 
   
const
+
// --------------------------------------------- STACK --------------------------------------------
  /// Ширина поля вывода
 
  PRINT_FIELD_WIDTH = 5;
 
  /// Разделитель при выводе элементов
 
  DELIMETR = '  ';
 
  /// Количество элементов, выводимых в одной строке при выводе
 
  ELEMS_IN_LINE = 5;
 
 
 
 
// ----------------------------------------------STACK---------------------------------------------
 
const
 
  /// Сообщение о пустоте стека
 
  EMPTY_STACK = 'Стек пуст';
 
 
 
type
 
type
 
   /// Шаблон класса Stack [Стек]
 
   /// Шаблон класса Stack [Стек]
Строка 892: Строка 205:
 
   private  
 
   private  
 
     /// Вершина стека
 
     /// Вершина стека
     fTop: SingleNode<DataType> := nil;   // field Top
+
     fTop: SingleNode<DataType> := nil;  
 
   
 
   
 
   public  
 
   public  
Строка 898: Строка 211:
 
     /// Создает пустой стек
 
     /// Создает пустой стек
 
     constructor Create;
 
     constructor Create;
    /// Создает стек, заполненный элементами, переданными в качестве параметров
 
    constructor Create(params xDatas : array of DataType);
 
 
   
 
   
     /// Кладет элемент x на вершину стека
+
    /// <summary>
 +
     /// Кладет элемент на вершину стека
 +
    /// </summary>
 +
    /// <param name="x">Новый элемент</param>
 
     procedure Push(x: DataType);
 
     procedure Push(x: DataType);
     /// Возвращает элемент типа DataType, снимая его с вершины стека
+
     /// Возвращает значение элемента на вершине, снимая его с вершины стека
 
     function Pop: DataType;
 
     function Pop: DataType;
     /// Возвращает значение элемента на вершине стека
+
     /// Возвращает значение элемента на вершине стека, не снимая его
 
     function Top: DataType;
 
     function Top: DataType;
 
   
 
   
 
     /// Возвращает истину, если стек пуст
 
     /// Возвращает истину, если стек пуст
     function IsEmpty: boolean;  
+
     function IsEmpty: boolean;  
     // ----------------------------- Вывод содержимого ---------------------------
+
     // ---------------------------------- Вывод ----------------------------------
    /// <summary>
+
     /// Выводит содержимое стека на консоль
     /// Выводит подряд содержимое стека
+
     procedure Println();
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
     procedure Print(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое стека в каждой строке
 
    procedure Println;
 
 
   end;
 
   end;
 
   
 
   
 
   
 
   
+
// --------------------------------------------- QUEUE --------------------------------------------
// ----------------------------------------------QUEUE---------------------------------------------
 
const
 
  /// Сообщение о пустоте очереди
 
  EMPTY_QUEUE = 'Очередь пуста';
 
 
 
type   
 
type   
 
   /// Шаблон класса Queue [Очередь]
 
   /// Шаблон класса Queue [Очередь]
Строка 941: Строка 244:
 
     /// Создает пустую очередь
 
     /// Создает пустую очередь
 
     constructor Create;
 
     constructor Create;
   
 
    /// Создает очередь, заполненную элементами, переданными в качестве параметров
 
    constructor Create(params xDatas: array of DataType);
 
 
   
 
   
     /// Добавляет элемент x в хвост очереди
+
    /// <summary>
 +
     /// Добавляет элемент в хвост очереди
 +
    /// </summary>
 +
    /// <param name="x">Добавляемый элемент</param>
 
     procedure Enqueue(x: DataType);
 
     procedure Enqueue(x: DataType);
   
+
     /// Возвращает значение элемента в голове, убирая его из головы очереди
     /// Возвращает элемент типа DataType, убирая его из головы очереди
 
 
     function Dequeue: DataType;
 
     function Dequeue: DataType;
   
+
     /// Возвращает значение элемента в голове очереди, не убирая его
     /// Возвращает значение головы очереди не убирая её
+
     function Top: DataType;
     function Top: DataType;  
 
 
      
 
      
 
     /// Возвращает истину, если очередь пуста
 
     /// Возвращает истину, если очередь пуста
 
     function IsEmpty: boolean;
 
     function IsEmpty: boolean;
 
+
   
     // ----------------------------- Вывод содержимого ---------------------------
+
     // ---------------------------------- Вывод ----------------------------------
    /// <summary>
+
     /// Выводит содержимое очереди на консоль
     /// Выводит подряд содержимое очереди от головы к хвосту
+
     procedure Println();
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
     procedure Print(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое очереди от головы к хвосту в каждой строке
 
    procedure Println;
 
 
   end;
 
   end;
 
   
 
   
 
   
 
   
+
// ------------------------------------------- DYN_ARRAY ------------------------------------------
// --------------------------------------------DYN_ARRAY-------------------------------------------
 
 
const
 
const
 
   /// Минимальная емкость, устанавливаемая при создании массива
 
   /// Минимальная емкость, устанавливаемая при создании массива
Строка 997: Строка 291:
 
     /// Создает массив размера pSize
 
     /// Создает массив размера pSize
 
     constructor Create(pSize: integer := 0);
 
     constructor Create(pSize: integer := 0);
   
 
    /// Создает массив, заполненный элементами, переданными в качестве параметров
 
    constructor Create(params xDatas: array of DataType);
 
 
   
 
   
     /// Выделяет новую память. Емкость увеличивается до newCap
+
    /// <summary>
     /// (Если newCap меньше текущей емкости, ничего не происходит)
+
     /// Выделяет новую память. Емкость увеличивается.
 +
     /// (Если newCap меньше текущей емкости, ничего не происходит)  
 +
    /// </summary>
 +
    /// <param name="newCap">Новая емкость массива</param>
 
     procedure Reserve(newCap: integer);
 
     procedure Reserve(newCap: integer);
      
+
     /// <summary>
     /// Устанавливает размер массива равным newSize
+
     /// Устанавливает новый размер массива  
 +
    /// </summary>
 +
    /// <param name="newSize">Новый размер массива</param>
 
     procedure Resize(newSize: integer);
 
     procedure Resize(newSize: integer);
 
   
 
   
     /// Добавляет элементы, переданные в качестве параметров, в конец массива
+
    /// <summary>
 +
     /// Добавляет элемент в конец массива  
 +
    /// </summary>
 +
    /// <param name="x">Добавляемый элемент</param>
 
     procedure Add(x: DataType);
 
     procedure Add(x: DataType);
      
+
     /// <summary>
     /// Добавляет элементы, переданные в качестве параметров, в конец массива
+
     /// Вставляет элемент в указанную позицию
    procedure Add(params xDatas: array of DataType);
+
     /// </summary>
      
+
     /// <param name="pos">Позиция, в которую вставляется элемент</param>
     /// Вставляет в массив элементы, переданные в качестве параметров,
+
     /// <param name="x">Вставляемый элемент</param>
     /// начиная с позиции pos
+
     procedure Insert(pos: integer; x: DataType);
     procedure Insert(pos: integer; params xDatas: array of DataType);
+
     /// <summary>
      
+
     /// Удаляет элемент массива из указанной позиции
     /// Удаляет count элементов массива, начиная с позиции pos.
+
     /// </summary>
     /// (По умолчанию удаляется один элемент)
+
    /// <param name="pos">Позиция, из которой удаляется элемент</param>
     procedure Delete(pos: integer; count: integer := 1);
+
     procedure Delete(pos: integer);
 
   
 
   
     /// Возвращает индекс первого элемента массива равного x
+
    /// <summary>
 +
     /// Возвращает индекс первого элемента массива равного искомому
 
     /// или -1, если такого элемента нет
 
     /// или -1, если такого элемента нет
 +
    /// </summary>
 +
    /// <param name="x">Искомый элемент</param>
 
     function Find(x: DataType): integer;
 
     function Find(x: DataType): integer;
   
+
    /// Возвращает индекс элемента массива равного x, начиная с позиции from,
 
    /// или -1, если такого элемента нет}
 
   
 
    function Find(x: DataType; from: integer): integer;
 
   
 
 
     // --------------------------------- Свойства --------------------------------
 
     // --------------------------------- Свойства --------------------------------
 
     /// Количество элементов (размер) массива
 
     /// Количество элементов (размер) массива
Строка 1036: Строка 333:
 
     /// Емкость массива (отведенная память)
 
     /// Емкость массива (отведенная память)
 
     property Capacity: integer read cap write Reserve;
 
     property Capacity: integer read cap write Reserve;
 +
   
 
     /// Позволяет обращаться к элементам массива по индексу  
 
     /// Позволяет обращаться к элементам массива по индексу  
 
     /// (например, apples[5])
 
     /// (например, apples[5])
 
     property Elem[index: integer]: DataType read GetElem write SetElem; default;
 
     property Elem[index: integer]: DataType read GetElem write SetElem; default;
     // ----------------------------- Вывод содержимого ---------------------------
+
 
    /// <summary>
+
     // ---------------------------------- Вывод ----------------------------------
     /// Выводит содержимое массива в прямом порядке
+
     /// Выводит содержимое массива на консоль
    /// </summary>
+
     procedure Println();
    /// <param name="delim">Разделитель между элементами в строке</param>
+
     /// Выводит содержимое массива в обратном порядке на консоль
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
+
     procedure PrintlnReverse();
     procedure Print(delim : string := DELIMETR; elemsInLine : integer := ELEMS_IN_LINE);
 
    /// <summary>
 
     /// Выводит содержимое массива в обратном порядке
 
    /// </summary>
 
    /// <param name="delim">Разделитель между элементами в строке</param>
 
    /// <param name="elemsInLine">Количество элементов, выводимых в одной строке</param>
 
     procedure PrintReverse(delim: string := DELIMETR; elemsInLine: integer := ELEMS_IN_LINE);
 
    /// Выводит содержимое массива в прямом порядке в каждой строке
 
    procedure Println;
 
    /// Выводит содержимое массива в обратном порядке в каждой строке
 
    procedure PrintlnReverse;
 
 
   end;
 
   end;
 
+
 
+
// ------------------------------------------- SIMPLE_SET -----------------------------------------
// --------------------------------------------SimpleSet-------------------------------------------
+
type  
type SimpleSet<DataType> = class  
+
  /// Шаблон класса SimpleSet [Простое множество]
 +
  SimpleSet<DataType> = class  
 
   private
 
   private
     data:=new DynArray<DataType>;
+
    /// Элементы множества
 +
     data := new DynArray<DataType>;
 +
   
 
   public
 
   public
 
     /// <summary>
 
     /// <summary>
Строка 1068: Строка 358:
 
     /// </summary>
 
     /// </summary>
 
     /// <param name="x">Добавляемый элемент</param>     
 
     /// <param name="x">Добавляемый элемент</param>     
     procedure Add(x:DataType);
+
     procedure Add(x: DataType);
         
 
 
     /// <summary>
 
     /// <summary>
 
     /// Удаляет элемент из множества
 
     /// Удаляет элемент из множества
 
     /// </summary>
 
     /// </summary>
 
     /// <param name="x">Удаляемый элемент</param>
 
     /// <param name="x">Удаляемый элемент</param>
     procedure Remove(x:DataType);
+
     procedure Remove(x: DataType);
         
+
 
     /// <summary>
 
     /// <summary>
     /// Проверяет, содержит ли множество элемент
+
     /// Возвращает истину, если множество содержит элемент
 
     /// </summary>
 
     /// </summary>
 
     /// <param name="x">Искомый элемент</param>           
 
     /// <param name="x">Искомый элемент</param>           
     function Contains(x:DataType):boolean;  
+
     function Contains(x: DataType): boolean;  
   
 
    ///Выводит содержимое множества на консоль
 
    procedure Print();
 
 
      
 
      
 +
    // ---------------------------------- Вывод ----------------------------------
 
     ///Выводит содержимое множества на консоль
 
     ///Выводит содержимое множества на консоль
 
     procedure Println();
 
     procedure Println();
 
end;
 
end;
    
+
 
    
+
// ------------------------------------------- ASSOC_ARRAY ----------------------------------------
    
+
type
    
+
   /// Шаблон класса AssocArray [Ассоциативный массив]
    
+
   AssocArray<KeyType, ValueType> = class
 
+
   private
 +
    /// Ключи
 +
    keys: DynArray<KeyType> := new DynArray<KeyType>;
 +
    /// Значения соответствующих ключей
 +
    values: DynArray<ValueType> := new DynArray<ValueType>;
 +
   
 +
    /// Устанавливает значение элемента с ключом key равным value
 +
    procedure SetElem(key: KeyType; value: ValueType);
 +
    /// Возвращает значение элемента с ключом key
 +
    function GetElem(key: KeyType): ValueType;
 +
   
 +
   public
 +
    // --------------------------------- Свойства --------------------------------
 +
    /// Позволяет обращаться к элементам массива по ключу
 +
    /// (Например, zoo['крокодил'])
 +
    property Elem[key: KeyType]: ValueType read GetElem write SetElem; default;
 +
   end;
 +
 +
 
  // ================================================================= IMPLEMENTATION ===================================================================
 
  // ================================================================= IMPLEMENTATION ===================================================================
 
implementation
 
implementation
 
   
 
   
 
   
 
   
+
// --------------------------------------------- STACK --------------------------------------------
// ----------------------------------------------STACK---------------------------------------------
+
   
 
 
// ---------------------------- Стандартные методы ---------------------------
 
// ---------------------------- Стандартные методы ---------------------------
{Стандартный конструктор}
+
{Создает пустой стек}
 
constructor Stack<DataType>.Create;
 
constructor Stack<DataType>.Create;
 
begin
 
begin
Строка 1108: Строка 412:
 
end;
 
end;
 
   
 
   
{Создает стек, заполненный элементами, переданными в качестве параметров}
+
{Кладет x элемент на вершину стека}  
constructor Stack<DataType>.Create(params xDatas: array of DataType);
 
begin
 
  fTop := nil;
 
  for var i := 0 to xDatas.Length - 1 do
 
    Push(xDatas[i]);
 
end;
 
 
{Кладет элемент x на вершину стека}  
 
 
procedure Stack<DataType>.Push(x: DataType);
 
procedure Stack<DataType>.Push(x: DataType);
 
begin
 
begin
Строка 1122: Строка 418:
 
end;
 
end;
 
   
 
   
{Возвращает элемент типа DataType, снимая его с вершины стека}
+
{Возвращает значение элемента на вершине, снимая его с вершины стека}
 
function Stack<DataType>.Pop: DataType;
 
function Stack<DataType>.Pop: DataType;
 
begin
 
begin
 
   if IsEmpty then  
 
   if IsEmpty then  
 
     raise new Exception('Попытка снятия элемента с пустого стека!');
 
     raise new Exception('Попытка снятия элемента с пустого стека!');
 +
   
 
   result := fTop.data;
 
   result := fTop.data;
 
   fTop := fTop.next;  // элемент снимается с вершины стека
 
   fTop := fTop.next;  // элемент снимается с вершины стека
Строка 1132: Строка 429:
 
end;
 
end;
 
   
 
   
{Возвращает значение элемента на вершине стека}
+
{Возвращает значение элемента на вершине стека, не снимая его}
 
function Stack<DataType>.Top: DataType;
 
function Stack<DataType>.Top: DataType;
 
begin
 
begin
 
   if IsEmpty then  
 
   if IsEmpty then  
 
     raise new Exception('Попытка получения элемента с пустого стека!');
 
     raise new Exception('Попытка получения элемента с пустого стека!');
 +
   
 
   result := fTop.data;
 
   result := fTop.data;
 
end;
 
end;
Строка 1146: Строка 444:
 
end;
 
end;
 
   
 
   
// ----------------------------- Вывод содержимого ---------------------------
+
// ---------------------------------- Вывод ----------------------------------
{Выводит подряд содержимое стека
+
{Выводит содержимое стека на консоль}
    delim — разделитель между элементами в строке
+
procedure Stack<DataType>.Println();
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure Stack<DataType>.Print(delim: string; elemsInLine: integer);
 
 
begin
 
begin
   if IsEmpty then
+
   if not IsEmpty then
    writeln(EMPTY_STACK)
 
  else
 
 
   begin
 
   begin
    var elemsInd := 1;  // индекс элемента стека
 
                        // нужен для вывода по строкам
 
 
     var curElem := fTop;
 
     var curElem := fTop;
 +
   
 
     while curElem <> nil do
 
     while curElem <> nil do
 
     begin
 
     begin
       if (elemsInd mod elemsInLine) <> 0 then
+
       write(curElem.data, ' ');
        write(curElem.data:PRINT_FIELD_WIDTH, delim)
 
      else              // вывели требуемое количество элементов в строке
 
        writeln(curElem.data:PRINT_FIELD_WIDTH, delim);
 
 
 
       curElem := curElem.next;
 
       curElem := curElem.next;
      elemsInd += 1;
 
    end;
 
  end;
 
end;
 
 
{Выводит содержимое стека в каждой строке}
 
procedure Stack<DataType>.Println;
 
begin
 
  if IsEmpty then
 
    writeln(EMPTY_STACK)
 
  else
 
  begin
 
    var curElem := fTop;
 
    while curElem <> nil do
 
    begin
 
      writeln(curElem.data:PRINT_FIELD_WIDTH);
 
      curElem := curElem.next;;
 
 
     end;
 
     end;
 
   end;
 
   end;
 +
  writeln();
 
end;
 
end;
 +
 
 
   
 
   
+
// --------------------------------------------- QUEUE --------------------------------------------
 
// ----------------------------------------------QUEUE---------------------------------------------
 
 
   
 
   
 
// ---------------------------- Стандартные методы ---------------------------
 
// ---------------------------- Стандартные методы ---------------------------
Строка 1200: Строка 472:
 
end;
 
end;
 
   
 
   
{Создает очередь, заполненную элементами, переданными в качестве параметров}
+
{Добавляет элемент ч в хвост очереди}  
constructor Queue<DataType>.Create(params xDatas: array of DataType);
 
begin
 
  head := nil;
 
  tail := nil;
 
  for var i := 0 to xDatas.Length - 1 do
 
    Enqueue(xDatas[i]);
 
end;
 
 
{Добавляет элемент x в хвост очереди}  
 
 
procedure Queue<DataType>.Enqueue(x: DataType);
 
procedure Queue<DataType>.Enqueue(x: DataType);
 
begin
 
begin
Строка 1217: Строка 480:
 
     tail := head;
 
     tail := head;
 
   end
 
   end
   else // if not IsEmpty
+
   else
 
   begin
 
   begin
 
     tail.next := new SingleNode<DataType>(x, nil);
 
     tail.next := new SingleNode<DataType>(x, nil);
Строка 1225: Строка 488:
 
end;
 
end;
 
   
 
   
{Возвращает элемент типа DataType, убирая его из головы очереди}
+
{Возвращает значение элемента в голове, убирая его из головы очереди}
 
function Queue<DataType>.Dequeue: DataType;
 
function Queue<DataType>.Dequeue: DataType;
 
begin
 
begin
 
   if IsEmpty then  
 
   if IsEmpty then  
 
     raise new Exception('Попытка удаления элемента из пустой очереди!');
 
     raise new Exception('Попытка удаления элемента из пустой очереди!');
 +
 
 
   result := head.data;
 
   result := head.data;
 
 
   head := head.next;  // элемент убирается из головы очереди
 
   head := head.next;  // элемент убирается из головы очереди
 
                       // (т.е. головой становится следующий элемент)
 
                       // (т.е. головой становится следующий элемент)
Строка 1237: Строка 500:
 
     tail := nil;
 
     tail := nil;
 
end;
 
end;
 
+
{Возвращает элемент типа DataType, не убирая его из головы очереди}
+
{Возвращает значение элемента в голове очереди, не убирая его}
 
function Queue<DataType>.Top: DataType;
 
function Queue<DataType>.Top: DataType;
 
begin
 
begin
 
   if IsEmpty then  
 
   if IsEmpty then  
 
     raise new Exception('Попытка получения элемента из пустой очереди!');
 
     raise new Exception('Попытка получения элемента из пустой очереди!');
 +
   
 
   result := head.data;
 
   result := head.data;
 
end;
 
end;
 
+
 
{Возвращает истину, если очередь пуста}
 
{Возвращает истину, если очередь пуста}
 
function Queue<DataType>.IsEmpty: boolean;
 
function Queue<DataType>.IsEmpty: boolean;
Строка 1254: Строка 518:
 
end;
 
end;
 
   
 
   
// ----------------------------- Вывод содержимого ---------------------------
+
// ---------------------------------- Вывод ----------------------------------
{Выводит подряд содержимое очереди от головы к хвосту
+
{Выводит содержимое очереди на консоль}
    delim — разделитель между элементами в строке
+
procedure Queue<DataType>.Println();
    elemsInLine — количество элементов, выводимых в одной строке}
 
procedure Queue<DataType>.Print(delim: string; elemsInLine: integer);
 
 
begin
 
begin
   if IsEmpty then
+
   if not IsEmpty then
    writeln(EMPTY_QUEUE)
 
  else
 
 
   begin
 
   begin
    var elemsInd := 1;  // индекс элемента стека
 
                        // нужен для вывода по строкам
 
 
     var curElem := head;
 
     var curElem := head;
 +
   
 
     while curElem <> nil do
 
     while curElem <> nil do
 
     begin
 
     begin
       if (elemsInd mod elemsInLine) <> 0 then
+
       write(curElem.data, ' ');
        write(curElem.data:PRINT_FIELD_WIDTH, delim)
 
      else              // вывели требуемое количество элементов в строке
 
        writeln(curElem.data:PRINT_FIELD_WIDTH, delim);
 
 
 
       curElem := curElem.next;
 
       curElem := curElem.next;
      elemsInd += 1;
 
 
     end;
 
     end;
 
   end;
 
   end;
 +
  writeln();
 
end;
 
end;
 
   
 
   
{Выводит содержимое очереди от головы к хвосту в каждой строке}
+
 
procedure Queue<DataType>.Println;
+
// -------------------------------------------DYN_ARRAY ------------------------------------------  
begin
+
 
  if IsEmpty then
 
    writeln(EMPTY_QUEUE)
 
  else
 
  begin
 
    var curElem := head;
 
    while curElem <> nil do
 
    begin
 
      writeln(curElem.data:PRINT_FIELD_WIDTH);
 
      curElem := curElem.next;;
 
    end;
 
  end;
 
end;
 
 
 
 
// --------------------------------------------DYN_ARRAY-------------------------------------------   
 
 
 
// ---------------------------- Стандартные методы ---------------------------
 
// ---------------------------- Стандартные методы ---------------------------
 
{Создает массив размера pSize}
 
{Создает массив размера pSize}
Строка 1309: Строка 547:
 
end;
 
end;
 
   
 
   
{Создает массив, заполненный элементами, переданными в качестве параметров}
+
{Выделяет новую память. Емкость увеличивается до newCap.
constructor DynArray<DataType>.Create(params xDatas: array of DataType);
+
  (Если newCap меньше текущей емкости, ничего не происходит) }
begin
 
  Create(xDatas.Length);  // Сначала нужно создать массив требуемого размера
 
 
  for var i := 0 to xDatas.Length - 1 do
 
    data[i] := xDatas[i];
 
end;
 
 
{Выделяет новую память. Емкость увеличивается до newCap
 
  (Если newCap меньше текущей емкости, ничего не происходит)}
 
 
procedure DynArray<DataType>.Reserve(newCap: integer);
 
procedure DynArray<DataType>.Reserve(newCap: integer);
 
begin
 
begin
Строка 1329: Строка 558:
 
end;
 
end;
 
   
 
   
{Устанавливает размер массива равным newSize}
+
{Устанавливает новый размер массива равным newSize}
 
procedure DynArray<DataType>.Resize(newSize: integer);
 
procedure DynArray<DataType>.Resize(newSize: integer);
 
begin
 
begin
   if newSize <= cap then
+
   if newSize > cap then
    size := newSize
 
  else
 
 
   begin
 
   begin
 
     Reserve(INC_CAP_FACTOR * newSize);
 
     Reserve(INC_CAP_FACTOR * newSize);
 
     for var i := size to newSize - 1 do // явным образом заполняем новые элементы
 
     for var i := size to newSize - 1 do // явным образом заполняем новые элементы
 
       data[i] := default(DataType);
 
       data[i] := default(DataType);
    size := newSize;
 
 
   end;
 
   end;
 +
  size := newSize;
 
end;
 
end;
 
   
 
   
{Добавляет элемент в конец массива}
+
{Добавляет элемент x в конец массива }
 
procedure DynArray<DataType>.Add(x: DataType);
 
procedure DynArray<DataType>.Add(x: DataType);
 
begin
 
begin
Строка 1350: Строка 577:
 
end;
 
end;
 
   
 
   
{Добавляет элементы, переданные в качестве параметров, в конец массива}
+
{Вставляет x элемент в позицию pos}
procedure DynArray<DataType>.Add(params xDatas: array of DataType);
+
procedure DynArray<DataType>.Insert(pos: integer; x: DataType);
begin
 
  Resize(size + xDatas.Length);
 
  for var i := 0 to xDatas.Length - 1 do
 
    data[size-xDatas.Length + i] := xDatas[i];
 
end;
 
 
{Вставляет в массив элементы, переданные в качестве параметров,
 
начиная с позиции pos}
 
procedure DynArray<DataType>.Insert(pos: integer; params xDatas: array of DataType);
 
 
begin
 
begin
 
   if (pos < 0) or (pos > size-1) then  
 
   if (pos < 0) or (pos > size-1) then  
     raise new Exception('Попытка вставки за границей массива в позицию ' + IntToStr(pos) + ' !');
+
     raise new Exception(
   Resize(size + xDatas.Length);
+
    'Попытка вставки за границей массива в позицию ' + IntToStr(pos) + '!');
   for var i := size - 2 downto pos+xDatas.Length - 1 do // сдвиг элементов вправо, начиная с позиции pos
+
   
     data[i+1] := data[i-xDatas.Length + 1];
+
   Resize(size + 1);
   for var i := 0 to xDatas.Length - 1 do                // заполнение "освободившихся" элементов новыми значениями
+
   for var i := size - 2 downto pos do
    data[pos+i] := xDatas[i];
+
     data[i+1] := data[i];
 +
   data[pos] := x;
 
end;
 
end;
 
   
 
   
{Удаляет count элементов массива, начиная с позиции pos.
+
{Удаляет элемент массива из позиции pos}
(По умолчанию удаляется один элемент)}
+
procedure DynArray<DataType>.Delete(pos: integer);
procedure DynArray<DataType>.Delete(pos: integer; count: integer);
 
 
begin
 
begin
 
   if (pos < 0) or (pos > size-1) then  
 
   if (pos < 0) or (pos > size-1) then  
     raise new Exception('Попытка удаления за границей массива из позиции ' + IntToStr(pos) + ' !');
+
     raise new Exception(
   
+
    'Попытка удаления за границей массива из позиции ' + IntToStr(pos) + '!');
  Assert((0 <= count) and (count <= size));
 
 
   
 
   
  if (size - pos) < count then          // если количество удаляемых элементов больше,
+
   for var i := pos to size - 2 do // сдвиг элементов влево на 1, начиная с позиции pos
                                        // чем их осталось до конца массива
+
     data[i] := data[i+1];
    count := size - pos;
+
   Resize(size - 1);
   for var i := pos to size-1 - count do // сдвиг элементов влево на count, начиная с позиции pos
 
     data[i] := data[i + count];
 
   Resize(size - count);                 // "отрезание" лишних count элементов
 
 
end;
 
end;
 
   
 
   
Строка 1400: Строка 614:
 
     end;
 
     end;
 
end;
 
end;
+
    
{Возвращает индекс элемента массива равного x, начиная с позиции from,
 
или -1, если такого элемента нет}
 
function DynArray<DataType>.Find(x: DataType; from: integer): integer;
 
begin
 
   if (from < 0) or (from > size-1) then
 
    raise new Exception('Попытка поиска за границей массива с позиции ' + IntToStr(from) + ' !');
 
 
  result := -1;
 
  for var i := from to size - 1 do
 
    if data[i] = x then
 
    begin
 
      result := i;
 
      exit;
 
    end;
 
end;
 
 
 
// ---------------------------- Доступ к элементам ---------------------------
 
// ---------------------------- Доступ к элементам ---------------------------
 
{Устанавливает элемент с индексом ind равным x}
 
{Устанавливает элемент с индексом ind равным x}
Строка 1422: Строка 620:
 
begin
 
begin
 
   if (ind < 0) or (ind > size-1) then  
 
   if (ind < 0) or (ind > size-1) then  
     raise new Exception('Попытка установки элемента за границей массива из позиции ' + IntToStr(ind) + ' !');
+
     raise new Exception(
 +
    'Попытка присвоить значение элементу за границей массива с индексом ' + IntToStr(ind) + '!');
 +
   
 
   data[ind] := x;
 
   data[ind] := x;
 
end;
 
end;
Строка 1430: Строка 630:
 
begin
 
begin
 
   if (ind < 0) or (ind > size-1) then  
 
   if (ind < 0) or (ind > size-1) then  
     raise new Exception('Попытка получения элемента за границей массива из позиции ' + IntToStr(ind) + ' !');
+
     raise new Exception(
 +
    'Попытка получить значение элемента за границей массива с индексом ' + IntToStr(ind) + '!');
 +
   
 
   result := data[ind];
 
   result := data[ind];
 
end;
 
end;
 
   
 
   
// ----------------------------- Вывод содержимого ---------------------------
+
// ---------------------------------- Вывод ----------------------------------
{Выводит содержимое массива в прямом порядке
+
{Выводит содержимое массива на консоль}
    delim — разделитель между элементами в строке
+
procedure DynArray<DataType>.Println();
    elemsInLine — количество элементов, выводимых в одной строке}
+
begin
procedure DynArray<DataType>.Print(delim: string; elemsInLine: integer);
+
  for var i := 0 to size - 1 do
 +
      write(data[i-1], ' ');
 +
end;
 +
 
 +
{Выводит содержимое массива в обратном порядке на консоль}
 +
procedure DynArray<DataType>.PrintlnReverse();
 
begin
 
begin
   for var i := 1 to size do
+
   for var i := size - 1 downto 0 do
    if (i mod elemsInLine) <> 0 then
+
       write(data[i-1], ' ');  
       write(data[i-1]:PRINT_FIELD_WIDTH, delim)
 
    else          // если вывели elemsInLine элементов, переходим на новую строку
 
      writeln(data[i-1]:PRINT_FIELD_WIDTH);
 
 
end;
 
end;
 
   
 
   
{Выводит содержимое массива в обратном порядке
+
    delim — разделитель между элементами в строке
+
// ------------------------------------------- SIMPLE_SET -----------------------------------------
     elemsInLine — количество элементов, выводимых в одной строке}
+
{Добавляет элемент x во множество}      
procedure DynArray<DataType>.PrintReverse(delim: string; elemsInLine: integer);
+
procedure SimpleSet<DataType>.Add(x: DataType);
 
begin
 
begin
   for var i := 1 to size do
+
   if data.Find(x) = -1 then  
    if (i mod elemsInLine) <> 0 then
+
    data.Add(x);
      write(data[size-i]:PRINT_FIELD_WIDTH, delim)
 
    else          // если вывели elemsInLine элементов, переходим на новую строку
 
      writeln(data[size-i]:PRINT_FIELD_WIDTH);
 
 
end;
 
end;
+
 
{Выводит содержимое массива в прямом порядке в каждой строке}
+
{Удаляет элемент x из множества}
procedure DynArray<DataType>.Println;
+
procedure SimpleSet<DataType>.Remove(x: DataType);
 
begin
 
begin
   for var i := 0 to size - 1 do
+
   var xPos := data.Find(x);
     writeln(data[i]);
+
  if xPos <> -1 then
 +
     data.Delete(xPos);
 
end;
 
end;
 
   
 
   
{Выводит содержимое массива в обратном порядке в каждой строке}
+
{Возвращает истину, если множество содержит элемент x}  
procedure DynArray<DataType>.PrintlnReverse;
+
function SimpleSet<DataType>.Contains(x: DataType): boolean;
 
begin
 
begin
   for var i := size - 1 downto 0 do
+
   result := (data.Find(x) <> -1);
    writeln(data[i]);
 
 
end;
 
end;
 
   
 
   
+
// ---------------------------------- Вывод ----------------------------------
+
  {Выводит содержимое множества на консоль}
// --------------------------------------------SimpleSet-------------------------------------------   
+
procedure SimpleSet<DataType>.Println();
{Удаляет элемент из множества}
 
procedure SimpleSet<DataType>.Remove(x:DataType);
 
 
begin
 
begin
   if data.Find(x)<>-1 then
+
   data.Println;
    data.Delete(data.Find(x),1);
 
 
end;
 
end;
  
{Добавляет элемент во множество}    
+
 
procedure SimpleSet<DataType>.Add(x:DataType);
+
// ------------------------------------------- ASSOC_ARRAY ----------------------------------------
 +
{Устанавливает значение элемента с ключом key равным value}
 +
procedure AssocArray<KeyType, ValueType>.SetElem(key: KeyType; value: ValueType);
 
begin
 
begin
   if data.Find(x)=-1 then  
+
   var ind := Keys.Find(key);
     data.Add(x);
+
  if ind <> -1 then
 +
     Values[ind] := value
 +
  else
 +
  begin
 +
    Keys.Add(key);
 +
    Values.Add(value);
 +
  end;
 
end;
 
end;
  
{Определяет, содержится ли элемент во множестве}  
+
{Возвращает значение элемента с ключом key}
function SimpleSet<DataType>.Contains(x:DataType):boolean;
+
function AssocArray<KeyType, ValueType>.GetElem(key: KeyType): ValueType;
 
begin
 
begin
   result:=data.Find(x)<>-1;
+
   var ind := Keys.Find(key);
end;
+
  if ind <> -1 then
   
+
    result := Values[ind]
{Печатает множество}      
+
  else
procedure SimpleSet<DataType>.Print();
+
  begin
begin
+
     Keys.Add(key);
   data.print(DELIMETR,ELEMS_IN_LINE);
+
    Values.Add(default(ValueType));
 +
    result := default(ValueType);
 +
   end;
 
end;
 
end;
 
{Печатает множество}   
 
procedure SimpleSet<DataType>.Println();
 
begin
 
  data.Println();
 
end;
 
 
  
 
end.
 
end.
 
</source>
 
</source>

Версия 15:52, 23 апреля 2009

Вспомогательные модули

Nodes

/// Модуль содержит шаблоны классов
///   SingleNode — узла с одним полем связи
///   DoubleNode — узла с двумя полями связи
unit Nodes;

interface

type

//-------------------------------------------SINGLE_NODE-------------------------------------------
  /// Узел с одним полем связи
  SingleNode<DataType> = class
    /// Значение узла
    data: DataType;
    /// Ссылка на следующий элемент
    next: SingleNode<DataType>;
    
    /// <summary>
    /// Конструктор
    /// </summary>
    /// <param name="pData">Значение узла</param>
    /// <param name="pNext">Ссылка на следующий элемент</param>
    constructor Create(pData: DataType; pNext: SingleNode<DataType>);
  end;

// -------------------------------------------DOUBLE_NODE------------------------------------------  
  /// Узел с двумя полями связи
  DoubleNode<DataType> = class
    /// Значение узла
    data: DataType;
    /// Ссылка на следующий элемент
    next: DoubleNode<DataType>;
    /// Ссылка на предыдущий элемент
    prev: DoubleNode<DataType>;
    
    /// <summary>
    /// Конструктор
    /// </summary>
    /// <param name="pData">Значение узла</param>
    /// <param name="pNext">Ссылка на следующий элемент</param>
    /// <param name="pPrev">Ссылка на предыдущий элемент</param>
    constructor Create(pData: DataType; pPrev, pNext: DoubleNode<DataType>);
  end;

implementation

//-------------------------------------------SINGLE_NODE-------------------------------------------
{Конструктор
    pData — значение узла
    pNext — cсылка на следующий элемент}
constructor SingleNode<DataType>.Create(pData: DataType; pNext: SingleNode<DataType>);
begin
  data := pData;
  next := pNext;
end;

// -------------------------------------------DOUBLE_NODE------------------------------------------  
{Конструктор
    pData — значение узла
    pNext — cсылка на следующий элемент
    pPrev — ссылка на предыдущий элемент}
constructor DoubleNode<DataType>.Create(pData: DataType; pPrev, pNext: DoubleNode<DataType>);
begin
  data := pData;
  next := pNext;
  prev := pPrev;
end;

end.

Collections

<xh4> Реализация </xh4>

/// Модуль содержит шаблоны классов
///   Stack — стек
///   Queue — очередь
///   DynArray — динамический массив с автоконтролем памяти
///   SimpleSet — простое множество (с минимальным набором операций)
///   AssocArray — ассоциативный массив
unit Collections;
 
interface
 
uses Nodes;   // для использования типа SingleNode<DataType> — 
              // узла с одним полем связи
  
 
// --------------------------------------------- STACK --------------------------------------------
type
  /// Шаблон класса Stack [Стек]
  Stack<DataType> = class
  private 
    /// Вершина стека
    fTop: SingleNode<DataType> := nil; 
 
  public 
    // ---------------------------- Стандартные методы ---------------------------
    /// Создает пустой стек
    constructor Create;
 
    /// <summary>
    /// Кладет элемент на вершину стека
    /// </summary>
    /// <param name="x">Новый элемент</param>
    procedure Push(x: DataType);
    /// Возвращает значение элемента на вершине, снимая его с вершины стека
    function Pop: DataType;
    /// Возвращает значение элемента на вершине стека, не снимая его
    function Top: DataType;
 
    /// Возвращает истину, если стек пуст
    function IsEmpty: boolean; 
    // ---------------------------------- Вывод ----------------------------------
    /// Выводит содержимое стека на консоль
    procedure Println();
  end;
 
 
// --------------------------------------------- QUEUE --------------------------------------------
type  
  /// Шаблон класса Queue [Очередь]
  Queue<DataType> = class
  private
    /// Голова очереди
    head: SingleNode<DataType>;
    /// Хвост очереди
    tail: SingleNode<DataType>;
 
  public
    // ---------------------------- Стандартные методы ---------------------------
    /// Создает пустую очередь
    constructor Create;
 
    /// <summary>
    /// Добавляет элемент в хвост очереди
    /// </summary>
    /// <param name="x">Добавляемый элемент</param>
    procedure Enqueue(x: DataType);
    /// Возвращает значение элемента в голове, убирая его из головы очереди
    function Dequeue: DataType;
    /// Возвращает значение элемента в голове очереди, не убирая его
    function Top: DataType;
    
    /// Возвращает истину, если очередь пуста
    function IsEmpty: boolean;
    
    // ---------------------------------- Вывод ----------------------------------
    /// Выводит содержимое очереди на консоль
    procedure Println();
  end;
 
 
// ------------------------------------------- DYN_ARRAY ------------------------------------------
const
  /// Минимальная емкость, устанавливаемая при создании массива
  MIN_CAP = 4;
  /// Коэффициент увеличения емкости массива при её нехватке
  INC_CAP_FACTOR = 2;
 
type
  /// Шаблон класса DynArray [Динамический массив с автоконтролем памяти]
  DynArray<DataType> = class
  private
    /// Встроенный динамический массив, содержащий данные
    data: array of DataType;
    /// Размер массива
    size: integer;
    /// Емкость массива
    cap: integer;
 
    /// Устанавливает элемент с индексом ind равным x
    procedure SetElem(ind: integer; x: DataType);
    /// Возвращает элемент массива с индексом ind
    function GetElem(ind: integer): DataType;
 
  public
    // ---------------------------- Стандартные методы ---------------------------
    /// Создает массив размера pSize
    constructor Create(pSize: integer := 0);
 
    /// <summary>
    /// Выделяет новую память. Емкость увеличивается.
    /// (Если newCap меньше текущей емкости, ничего не происходит) 
    /// </summary>
    /// <param name="newCap">Новая емкость массива</param>
    procedure Reserve(newCap: integer);
    /// <summary>
    /// Устанавливает новый размер массива 
    /// </summary>
    /// <param name="newSize">Новый размер массива</param>
    procedure Resize(newSize: integer);
 
    /// <summary>
    /// Добавляет элемент в конец массива 
    /// </summary>
    /// <param name="x">Добавляемый элемент</param>
    procedure Add(x: DataType);
    /// <summary>
    /// Вставляет элемент в указанную позицию
    /// </summary>
    /// <param name="pos">Позиция, в которую вставляется элемент</param>
    /// <param name="x">Вставляемый элемент</param>
    procedure Insert(pos: integer; x: DataType);
    /// <summary>
    /// Удаляет элемент массива из указанной позиции
    /// </summary>
    /// <param name="pos">Позиция, из которой удаляется элемент</param>
    procedure Delete(pos: integer);
 
    /// <summary>
    /// Возвращает индекс первого элемента массива равного искомому
    /// или -1, если такого элемента нет
    /// </summary>
    /// <param name="x">Искомый элемент</param>
    function Find(x: DataType): integer;
 
    // --------------------------------- Свойства --------------------------------
    /// Количество элементов (размер) массива
    property Count: integer read size write Resize;
    /// Емкость массива (отведенная память)
    property Capacity: integer read cap write Reserve;
    
    /// Позволяет обращаться к элементам массива по индексу 
    /// (например, apples[5])
    property Elem[index: integer]: DataType read GetElem write SetElem; default;

    // ---------------------------------- Вывод ----------------------------------
    /// Выводит содержимое массива на консоль
    procedure Println();
    /// Выводит содержимое массива в обратном порядке на консоль
    procedure PrintlnReverse();
  end;
 
// ------------------------------------------- SIMPLE_SET -----------------------------------------
type 
  /// Шаблон класса SimpleSet [Простое множество]
  SimpleSet<DataType> = class 
  private
    /// Элементы множества
    data := new DynArray<DataType>;
    
  public
    /// <summary>
    /// Добавляет элемент в множество
    /// </summary>
    /// <param name="x">Добавляемый элемент</param>    
    procedure Add(x: DataType);
    /// <summary>
    /// Удаляет элемент из множества
    /// </summary>
    /// <param name="x">Удаляемый элемент</param>
    procedure Remove(x: DataType);
 
    /// <summary>
    /// Возвращает истину, если множество содержит элемент
    /// </summary>
    /// <param name="x">Искомый элемент</param>          
    function Contains(x: DataType): boolean;   
    
    // ---------------------------------- Вывод ----------------------------------
    ///Выводит содержимое множества на консоль
    procedure Println();
end;

// ------------------------------------------- ASSOC_ARRAY ----------------------------------------
type
  /// Шаблон класса AssocArray [Ассоциативный массив]
  AssocArray<KeyType, ValueType> = class
  private
    /// Ключи
    keys: DynArray<KeyType> := new DynArray<KeyType>;
    /// Значения соответствующих ключей
    values: DynArray<ValueType> := new DynArray<ValueType>;
    
    /// Устанавливает значение элемента с ключом key равным value
    procedure SetElem(key: KeyType; value: ValueType);
    /// Возвращает значение элемента с ключом key
    function GetElem(key: KeyType): ValueType;
    
  public
    // --------------------------------- Свойства --------------------------------
    /// Позволяет обращаться к элементам массива по ключу
    /// (Например, zoo['крокодил'])
    property Elem[key: KeyType]: ValueType read GetElem write SetElem; default;
  end;
 
 
 // ================================================================= IMPLEMENTATION ===================================================================
implementation
 
 
// --------------------------------------------- STACK --------------------------------------------
    
// ---------------------------- Стандартные методы ---------------------------
{Создает пустой стек}
constructor Stack<DataType>.Create;
begin
  fTop := nil;
end;
 
{Кладет x элемент на вершину стека} 
procedure Stack<DataType>.Push(x: DataType);
begin
  fTop := new SingleNode<DataType>(x, fTop);
end;
 
{Возвращает значение элемента на вершине, снимая его с вершины стека}
function Stack<DataType>.Pop: DataType;
begin
  if IsEmpty then 
     raise new Exception('Попытка снятия элемента с пустого стека!');
     
  result := fTop.data;
  fTop := fTop.next;  // элемент снимается с вершины стека
                      // (т.е. вершиной становится следующий элемент)
end;
 
{Возвращает значение элемента на вершине стека, не снимая его}
function Stack<DataType>.Top: DataType;
begin
  if IsEmpty then 
     raise new Exception('Попытка получения элемента с пустого стека!');
     
  result := fTop.data;
end;
 
{Возвращает истину, если стек пуст}
function Stack<DataType>.IsEmpty: boolean;
begin
  result := (fTop = nil);
end;
 
// ---------------------------------- Вывод ----------------------------------
{Выводит содержимое стека на консоль}
procedure Stack<DataType>.Println();
begin
  if not IsEmpty then
  begin
    var curElem := fTop;
    
    while curElem <> nil do
    begin
      write(curElem.data, ' ');
      curElem := curElem.next;
    end;
  end;
  writeln();
end;
  
 
// --------------------------------------------- QUEUE --------------------------------------------
 
// ---------------------------- Стандартные методы ---------------------------
{Создает пустую очередь}
constructor Queue<DataType>.Create;
begin
  head := nil;
  tail := nil;
end;
 
{Добавляет элемент ч в хвост очереди} 
procedure Queue<DataType>.Enqueue(x: DataType);
begin
  if IsEmpty then
  begin
    head := new SingleNode<DataType>(x, nil);
    tail := head;
  end
  else
  begin
    tail.next := new SingleNode<DataType>(x, nil);
    tail := tail.next;  // элемент убирается из хвоста очереди
                        // (т.е. хвостом становится следующий элемент)
  end;
end;
 
{Возвращает значение элемента в голове, убирая его из головы очереди}
function Queue<DataType>.Dequeue: DataType;
begin
  if IsEmpty then 
     raise new Exception('Попытка удаления элемента из пустой очереди!');
  
  result := head.data;
  head := head.next;  // элемент убирается из головы очереди
                      // (т.е. головой становится следующий элемент)
  if head = nil then
    tail := nil;
end;
 
{Возвращает значение элемента в голове очереди, не убирая его}
function Queue<DataType>.Top: DataType;
begin
  if IsEmpty then 
     raise new Exception('Попытка получения элемента из пустой очереди!');
     
  result := head.data;
end;
 
{Возвращает истину, если очередь пуста}
function Queue<DataType>.IsEmpty: boolean;
begin
  result := (head = nil);
  if result then
    Assert(tail = nil);
end;
 
// ---------------------------------- Вывод ----------------------------------
{Выводит содержимое очереди на консоль}
procedure Queue<DataType>.Println();
begin
  if not IsEmpty then
  begin
    var curElem := head;
    
    while curElem <> nil do
    begin
      write(curElem.data, ' ');
      curElem := curElem.next;
    end;
  end;
  writeln();
end;
 

// -------------------------------------------DYN_ARRAY ------------------------------------------   

// ---------------------------- Стандартные методы ---------------------------
{Создает массив размера pSize}
constructor DynArray<DataType>.Create(pSize: integer);
begin
  size := pSize;
  cap := INC_CAP_FACTOR*pSize + MIN_CAP; // Устанавливаем емкость "с запасом"
  SetLength(data, cap);
end;
 
{Выделяет новую память. Емкость увеличивается до newCap.
 (Если newCap меньше текущей емкости, ничего не происходит) }
procedure DynArray<DataType>.Reserve(newCap: integer);
begin
  if newCap > cap then 
  begin
    SetLength(data, newCap);
    cap := newCap;
  end;
end;
 
{Устанавливает новый размер массива равным newSize}
procedure DynArray<DataType>.Resize(newSize: integer);
begin
  if newSize > cap then
  begin
    Reserve(INC_CAP_FACTOR * newSize);
    for var i := size to newSize - 1 do // явным образом заполняем новые элементы
      data[i] := default(DataType);
  end;
  size := newSize;
end;
 
{Добавляет элемент x в конец массива }
procedure DynArray<DataType>.Add(x: DataType);
begin
  Resize(size + 1);
  data[size-1] := x;
end;
 
{Вставляет x элемент в позицию pos}
procedure DynArray<DataType>.Insert(pos: integer; x: DataType);
begin
  if (pos < 0) or (pos > size-1) then 
     raise new Exception(
     'Попытка вставки за границей массива в позицию ' + IntToStr(pos) + '!');
     
  Resize(size + 1);
  for var i := size - 2 downto pos do
    data[i+1] := data[i];
  data[pos] := x;
end;
 
{Удаляет элемент массива из позиции pos}
procedure DynArray<DataType>.Delete(pos: integer);
begin
  if (pos < 0) or (pos > size-1) then 
     raise new Exception(
     'Попытка удаления за границей массива из позиции ' + IntToStr(pos) + '!');
 
  for var i := pos to size - 2 do // сдвиг элементов влево на 1, начиная с позиции pos
    data[i] := data[i+1];
  Resize(size - 1);
end;
 
{Возвращает индекс первого элемента массива равного x
 или -1, если такого элемента нет}
function DynArray<DataType>.Find(x: DataType): integer;
begin
  result := -1;
  for var i := 0 to size - 1 do
    if data[i] = x then
    begin
      result := i;
      exit;
    end;
end;
  
// ---------------------------- Доступ к элементам ---------------------------
{Устанавливает элемент с индексом ind равным x}
procedure DynArray<DataType>.SetElem(ind: integer; x: DataType);
begin
  if (ind < 0) or (ind > size-1) then 
     raise new Exception(
     'Попытка присвоить значение элементу за границей массива с индексом ' + IntToStr(ind) + '!');
     
  data[ind] := x;
end;
 
{Возвращает элемент массива с индексом ind}
function DynArray<DataType>.GetElem(ind: integer): DataType;
begin
  if (ind < 0) or (ind > size-1) then 
     raise new Exception(
     'Попытка получить значение элемента за границей массива с индексом ' + IntToStr(ind) + '!');
     
  result := data[ind];
end;
 
// ---------------------------------- Вывод ----------------------------------
{Выводит содержимое массива на консоль}
procedure DynArray<DataType>.Println();
begin
  for var i := 0 to size - 1 do
      write(data[i-1], ' '); 
end;

{Выводит содержимое массива в обратном порядке на консоль}
procedure DynArray<DataType>.PrintlnReverse();
begin
  for var i := size - 1 downto 0 do
      write(data[i-1], ' '); 
end;
 
 
// ------------------------------------------- SIMPLE_SET -----------------------------------------
{Добавляет элемент x во множество}     
procedure SimpleSet<DataType>.Add(x: DataType);
begin
  if data.Find(x) = -1 then 
    data.Add(x);
end;

{Удаляет элемент x из множества}
procedure SimpleSet<DataType>.Remove(x: DataType);
begin
  var xPos := data.Find(x);
  if xPos <> -1 then
    data.Delete(xPos);
end;
 
{Возвращает истину, если множество содержит элемент x}    
function SimpleSet<DataType>.Contains(x: DataType): boolean;
begin
  result := (data.Find(x) <> -1);
end;
 
// ---------------------------------- Вывод ----------------------------------
 {Выводит содержимое множества на консоль}
procedure SimpleSet<DataType>.Println();
begin
  data.Println;
end;


// ------------------------------------------- ASSOC_ARRAY ----------------------------------------
{Устанавливает значение элемента с ключом key равным value}
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;

{Возвращает значение элемента с ключом key}
function AssocArray<KeyType, ValueType>.GetElem(key: KeyType): ValueType;
begin
  var ind := Keys.Find(key);
  if ind <> -1 then
    result := Values[ind]
  else
  begin
    Keys.Add(key);
    Values.Add(default(ValueType));
    result := default(ValueType);
  end;
end;

end.