Осторожно: очень много костылей! Это лишь чтоб показать идею.
type
RectList<T> = class
private mtx:array[,] of T;
private l1,l2:integer;
private function GetItem(i1,i2:integer):T;
begin
if cardinal(i1) > cardinal(l1) then raise new System.IndexOutOfRangeException('i1 неправильный') else
if cardinal(i2) > cardinal(l2) then raise new System.IndexOutOfRangeException('i2 неправильный') else
Result := mtx[i1,i2];
end;
private procedure SetItem(i1,i2:integer; o:T) :=
if cardinal(i1) > cardinal(l1) then raise new System.IndexOutOfRangeException('i1 неправильный') else
if cardinal(i2) > cardinal(l2) then raise new System.IndexOutOfRangeException('i2 неправильный') else
mtx[i1,i2] := o;
public constructor;
begin
mtx := new T[4,4];
end;
public procedure Resize(nl1,nl2:integer);
begin
var res := new T[nl1,nl2];
//ToDo реализовать через System.Array.Copy, так быстрее
//Только копировать придётся построчно, иначе не сработает
for var i1 := 0 to Min(Cap1,nl1)-1 do
for var i2 := 0 to Min(Cap2,nl2)-1 do
res[i1,i2] := mtx[i1,i2];
mtx := res;
end;
public property Length1:integer read l1;
public property Length2:integer read l2;
public property Cap1:integer read mtx.GetLength(0) write Resize(value,Cap2);
public property Cap2:integer read mtx.GetLength(1) write Resize(Cap1,value);
public property Item[i1,i2:integer]:T read GetItem write SetItem; default;
public procedure Add1(o:ICollection<T>; at:integer);
begin
if cardinal(at) > cardinal(l1) then raise new System.IndexOutOfRangeException('at неправильный');
var ol := o.Count;
if ol > l2 then raise new System.IndexOutOfRangeException('o.Count неправильный');
if l1 = Cap1 then Resize(Cap1*2, Cap2);
//ToDo опять же, через Array.Copy надо
for var i1 := l1-1 downto at do
for var i2 := 0 to l2-1 do
mtx[i1+1,i2] := mtx[i1,i2];
var i2 := 0;
foreach var a in o do
begin
mtx[at, i2] := a;
i2 += 1;
end;
l1 += 1;
end;
public procedure Add2(o:ICollection<T>; at:integer);
begin
if cardinal(at) > cardinal(l2) then raise new System.IndexOutOfRangeException('at неправильный');
var ol := o.Count;
if ol > l1 then raise new System.IndexOutOfRangeException('o.Count неправильный');
if l2 = Cap2 then Resize(Cap1, Cap2*2);
//ToDo опять же, через Array.Copy надо
for var i2 := l2-1 downto at do
for var i1 := 0 to l1-1 do
mtx[i1,i2+1] := mtx[i1,i2];
var i1 := 0;
foreach var a in o do
begin
mtx[i1, at] := a;
i1 += 1;
end;
l2 += 1;
end;
public procedure Remove1(at:integer);
begin
if cardinal(at) > cardinal(l1) then raise new System.IndexOutOfRangeException('at неправильный');
//ToDo опять же, через Array.Copy надо
for var i1 := at to l1-1 do
for var i2 := 0 to l2-1 do
mtx[i1,i2] := mtx[i1+1,i2];
l1 -= 1;
end;
public procedure Remove2(at:integer);
begin
if cardinal(at) > cardinal(l2) then raise new System.IndexOutOfRangeException('at неправильный');
//ToDo опять же, через Array.Copy надо
for var i2 := at to l2-1 do
for var i1 := 0 to l1-1 do
mtx[i1,i2] := mtx[i1,i2+1];
l2 -= 1;
end;
class function operator implicit(a: RectList<T>): array[,] of T;
begin
Result := new T[a.l1,a.l2];
//ToDo опять же, через Array.Copy надо
for var i1 := 0 to a.l1-1 do
for var i2 := 0 to a.l2-1 do
Result[i1,i2] := a.mtx[i1,i2];
end;
end;
begin
var mtx := new RectList<byte>;
mtx.Resize(3,3);
mtx.l2 := 3;//так вообще не даст сделать в нормальном коде, надо как то лучше реализовать.
mtx.Add1(new byte[](10,11,12),0);
mtx.Add1(new byte[](13,14,15),1);
mtx.Add1(new byte[](16,17,18),2);
var res: array[,] of byte := mtx;
res.Println;
writeln;
mtx.Add1(new byte[](21,22,23),1);
mtx.Add2(new byte[](31,32,33,34),1);
res := mtx;
res.Println;
end.
Примерно так же реализован обычный список.
А связный список - этот тот, в котором после каждого элемента идёт ссылка на следующий. Таким образом прямо в его центр можно вставить что то, без особых проблем. Хотя, конечно, получение элемента по индексу - ужасно медленное, из за того, сколько указателей придётся разыменовывать. Он полезен только если надо вставить много элементов в разные места. Тогда надо сначала преобразовать массив к связному списку, потому добавить/убрать всё что надо, а потом преобразовать назад в массив.