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

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Collections)
м (Правки 87.117.60.143 (обсуждение) откачены к версии 195.208.237.241)
Строка 79: Строка 79:
 
///  Stack — стек
 
///  Stack — стек
 
///  Queue — очередь
 
///  Queue — очередь
///  DynArray — динамический массив с автоконтролем памяти
 
 
unit Collections;
 
unit Collections;
 
   
 
   
 
   
 
   
 +
// ===================================================================== INTERFACE =====================================================================
 
interface
 
interface
 
   
 
   
Строка 107: Строка 107:
 
     /// Вершина стека
 
     /// Вершина стека
 
     fTop: SingleNode<DataType> := nil;  // field Top
 
     fTop: SingleNode<DataType> := nil;  // field Top
   
 
 
   public  
 
   public  
 
// ---------------------------- Стандартные методы ---------------------------  
 
// ---------------------------- Стандартные методы ---------------------------  
    /// Создает пустой стек
+
  /// Стандартный конструктор
 
     constructor Create;
 
     constructor Create;
 +
    /// Конструктор.
 
     /// Создает стек, заполненный элементами, переданными в качестве параметров
 
     /// Создает стек, заполненный элементами, переданными в качестве параметров
     constructor Create(params xDatas : array of DataType);  
+
     constructor Create(params datas: array of DataType);  
 
   
 
   
 
     /// Кладет элемент x на вершину стека
 
     /// Кладет элемент x на вершину стека
Строка 121: Строка 121:
 
     /// Возвращает значение элемента на вершине стека
 
     /// Возвращает значение элемента на вершине стека
 
     function Top: DataType;
 
     function Top: DataType;
   
 
 
     /// Возвращает истину, если стек пуст
 
     /// Возвращает истину, если стек пуст
     function IsEmpty: boolean;  
+
     function IsEmpty: boolean;
 
// ----------------------------- Вывод содержимого ---------------------------
 
// ----------------------------- Вывод содержимого ---------------------------
 
     /// <summary>
 
     /// <summary>
Строка 148: Строка 147:
 
     /// Хвост очереди
 
     /// Хвост очереди
 
     tail: SingleNode<DataType>;
 
     tail: SingleNode<DataType>;
   
 
 
   public
 
   public
 
// ---------------------------- Стандартные методы ---------------------------
 
// ---------------------------- Стандартные методы ---------------------------
     /// Создает пустую очередь
+
     /// Стандартный конструктор
 
     constructor Create;
 
     constructor Create;
 +
    /// Конструктор.
 
     /// Создает очередь, заполненную элементами, переданными в качестве параметров
 
     /// Создает очередь, заполненную элементами, переданными в качестве параметров
     constructor Create(params xDatas: array of DataType);  
+
     constructor Create(params datas: array of DataType);  
   
 
 
     /// Добавляет элемент x в хвост очереди
 
     /// Добавляет элемент x в хвост очереди
 
     procedure Enqueue(x: DataType);
 
     procedure Enqueue(x: DataType);
Строка 161: Строка 159:
 
     function Dequeue: DataType;
 
     function Dequeue: DataType;
 
     /// Возвращает истину, если очередь пуста
 
     /// Возвращает истину, если очередь пуста
   
 
 
     function IsEmpty: boolean;
 
     function IsEmpty: boolean;
 
// ----------------------------- Вывод содержимого ---------------------------
 
// ----------------------------- Вывод содержимого ---------------------------
Строка 174: Строка 171:
 
   end;
 
   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);
 
    /// Создает массив, заполненный элементами, переданными в качестве параметров
 
    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 ===================================================================
Строка 263: Строка 183:
 
   fTop := nil;
 
   fTop := nil;
 
end;
 
end;
{Создает стек, заполненный элементами, переданными в качестве параметров}
+
{Конструктор.
constructor Stack<DataType>.Create(params xDatas: array of DataType);  
+
Создает стек, заполненный элементами, переданными в качестве параметров}
 +
constructor Stack<DataType>.Create(params datas: array of DataType);  
 
begin
 
begin
 
   fTop := nil;
 
   fTop := nil;
   for var i := 0 to xDatas.Length - 1 do
+
   for var i := 0 to datas.Length - 1 do
     Push(xDatas[i]);
+
     Push(datas[i]);
 
end;
 
end;
 
   
 
   
Строка 344: Строка 265:
 
   
 
   
 
// ---------------------------- Стандартные методы ---------------------------
 
// ---------------------------- Стандартные методы ---------------------------
{Создает пустую очередь}
+
{Конструктор}
 
constructor Queue<DataType>.Create;
 
constructor Queue<DataType>.Create;
 
begin
 
begin
Строка 350: Строка 271:
 
   tail := nil;
 
   tail := nil;
 
end;
 
end;
{Создает очередь, заполненную элементами, переданными в качестве параметров}
+
{Конструктор.
constructor Queue<DataType>.Create(params xDatas: array of DataType);  
+
Создает очередь, заполненную элементами, переданными в качестве параметров}
 +
constructor Queue<DataType>.Create(params datas: array of DataType);  
 
begin
 
begin
 
   head := nil;
 
   head := nil;
 
   tail := nil;
 
   tail := nil;
   for var i := 0 to xDatas.Length - 1 do
+
   for var i := 0 to datas.Length - 1 do
     Enqueue(xDatas[i]);
+
     Enqueue(datas[i]);
 
end;
 
end;
 
   
 
   
Строка 435: Строка 357:
 
     end;
 
     end;
 
   end;
 
   end;
end;
 
 
// --------------------------------------------DYN_ARRAY-------------------------------------------   
 
 
// ---------------------------- Стандартные методы ---------------------------
 
{Создает массив размера pSize}
 
constructor DynArray<DataType>.Create(pSize: integer);
 
begin
 
  size := pSize;
 
  cap := 2*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.
 
end.
 
</source>
 
</source>

Версия 11:03, 19 апреля 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

/// Модуль содержит шаблоны классов
///   Stack — стек
///   Queue — очередь
unit Collections;
 
 
// ===================================================================== INTERFACE =====================================================================
interface
 
uses Nodes;   // для использования типа SingleNode<DataType> — 
              // узла с одним полем связи
 
const
  /// Ширина поля вывода
  PRINT_FIELD_WIDTH = 5;
  /// Разделитель при выводе элементов
  DELIMETR = '   ';
  /// Количество элементов, выводимых в одной строке при выводе
  ELEMS_IN_LINE = 5;
 
// ----------------------------------------------STACK---------------------------------------------
const
  /// Сообщение о пустоте стека
  EMPTY_STACK = 'Стек пуст';
 
type
  /// Шаблон класса Stack [Стек]
  Stack<DataType> = class
  private 
    /// Вершина стека
    fTop: SingleNode<DataType> := nil;   // field Top
  public 
// ---------------------------- Стандартные методы --------------------------- 
   /// Стандартный конструктор
    constructor Create;
    /// Конструктор.
    /// Создает стек, заполненный элементами, переданными в качестве параметров
    constructor Create(params datas: 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;
 
// ----------------------------------------------QUEUE---------------------------------------------
const
  /// Сообщение о пустоте очереди
  EMPTY_QUEUE = 'Очередь пуста';

type  
  /// Шаблон класса Queue [Очередь]
  Queue<DataType> = class
  private
    /// Голова очереди
    head: SingleNode<DataType>;
    /// Хвост очереди
    tail: SingleNode<DataType>;
  public
// ---------------------------- Стандартные методы ---------------------------
    /// Стандартный конструктор
    constructor Create;
    /// Конструктор.
    /// Создает очередь, заполненную элементами, переданными в качестве параметров
    constructor Create(params datas: 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
 
// ----------------------------------------------STACK---------------------------------------------
 
// ---------------------------- Стандартные методы ---------------------------
{Стандартный конструктор}
constructor Stack<DataType>.Create;
begin
  fTop := nil;
end;
{Конструктор.
 Создает стек, заполненный элементами, переданными в качестве параметров}
constructor Stack<DataType>.Create(params datas: array of DataType); 
begin
  fTop := nil;
  for var i := 0 to datas.Length - 1 do
    Push(datas[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;
 
// ----------------------------------------------QUEUE---------------------------------------------
 
// ---------------------------- Стандартные методы ---------------------------
{Конструктор}
constructor Queue<DataType>.Create;
begin
  head := nil;
  tail := nil;
end;
{Конструктор.
 Создает очередь, заполненную элементами, переданными в качестве параметров}
constructor Queue<DataType>.Create(params datas: array of DataType); 
begin
  head := nil;
  tail := nil;
  for var i := 0 to datas.Length - 1 do
    Enqueue(datas[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.