Фундаментальные алгоритмы и структуры данных в Delphi | страница 41
destructor TtdRecordList.Destroy
begin
Capacity := 0;
inherited Destroy;
end;
А теперь давайте перейдем к более интересным вещам: добавлению и вставке новых элементов. Реализация метода Add достаточно проста. В ней вызывается Insert для вставки нового элемента в конец массива. Метод Insert в качестве входного параметра принимает значение, представляющее собой индекс позиции, в которую требуется вставить новый элемент. Сам элемент задается указателем (есть еще один способ представления вставляемого элемента - в виде нетипизированного параметра var, однако указатели позволяют упростить реализацию и понимание других методов и, кроме того, обеспечивают непротиворечивость). При вызове метода Insert для передачи адреса вставляемого элемента в виде указателя используется операция 8, определенная в Delphi.
Поскольку новый элемент является указателем, он может содержать nil, поэтому сначала необходимо проверить, что указатель не равен nil. Затем в реализации метода выполняется проверка выхода индекса за границы допустимого диапазона. Только после этого можно приступить к собственно вставке. Если количество элементов равно текущей емкости массива, то для расширения массива вызывается метод rlExpand Теперь мы перемещаем элементы, начиная с индекса aIndex до конца массива, на один элемент, дабы тем самым освободить место под новый элемент. И, наконец, мы вставляем элемент в образовавшуюся "дыру" и увеличиваем значение счетчика элементов на единицу.
Листинг 2.4. Добавление и вставка новых элементов
function TtdRecordList.Add(aItem : pointer): integer;
begin
Result := Count;
Insert(Count, aItem);
end;
procedure TtdRecordList.Insert(aIndex : integer;
aItem : pointer);
begin
if (aItem = nil) then
rlError(tdeNilItem, 'Insert', aIndex);
if (aIndex < 0) or (aIndex > Count) then
rlError(tdeIndexOutOfBounds, 'Insert', aIndex);
if (Count = Capacity) then
rlExpand;
if (aIndex < Count) then
System.Move((FArray + (aIndex * FElementSize))^,
(FArray+ (succ(aIndex) * FElementSize))^,
(Count - aIndex) * FElementSize);
System.Move (aItem^,
(FArray + (aIndex * FElementSize))^, FActElemSize);
inc(FCount);
end;
Реализация метода Delete, предназначенного для удаления элементов из массива, показана в листинге 2.5. Как и для Insert, сначала проверяется переданный методу индекс, затем элементы, начиная с индекса aIndex, переносятся на одну позицию к началу массива, за счет чего требуемый элемент удаляется. После удаления количество элементов в массиве уменьшается, поэтому из значения счетчика элементов вычитается единица.