Модуль для работы с динамическими массивами.
Модуль позволяет работать с массивами с динамической длинной
Constructor INIT;
Инициализирует массив. Требуется запустить лишь один раз - в начале работы с массивом, но после определения начальной длины
Procedure SetSizeArray(_Size:word);
Устанавливает длинну массива равную _Size. При первом запуске, после нее требуется запустить конструктор.
Function GetSizeArray:Word;
Возвращает текущую длинну массива. Лучше использовать ее и не открывать доступ к переменной sizeofarray, т.к. последствия могут быть непредсказуемые.
Procedure EnteringArray(visible:Byte;VideoMode:Byte);
Процедура ввода массива.
Не очень надежна, т.к. нет поддержки backspace, но зато возможен ввод в графическом режиме и возможно управлять отображением вводимых чисел. (Для вывода, скажем звездочек вместо вводимых символов, ставим параметр visible=<код звездочки>
Videomode может иметь RText или RGraph - соответственно ввод в текстовом и ввод в графическом режиме.
Внимание: если тип режима указан неверно, произойдет ошибка периода исполнения.
Procedure PrintCRTarray(Videomode:byte);
Вывод на экран массива. Возможны 2 режима как и у метода для ввода массива.
Procedure QSort(left,right:integer);
Быстрая сортировка массива.
Procedure HSort;
Пирамидальная сортировка массива. Полезна если вы уверены что массив почти или полностью отсортирован.
Function GetMaxElem:Telem;
Возвращает максимальный элемент массива.
Function GetMinElem:Telem;
Возвращает мимнимальный элемент массива.
Function GetNumMaxElem:Word;
Возвращает номер максимального элемента в массиве. (Первого, если таких элементов несколько)
Function GetNumMinElem:Word;
Возвращает номер минимального элемента.
Function ElemInArray(T:Telem):Word;
Проверяет вхождение элемента в массив. 0 - если не найдено, иначе индекс элемента.
Procedure InvertArray;
Инвертирует массив.
Вот программа демонстрирующая возможности модуля.
Работа с динамическими массивами
Для того, чтобы работать с динамическими массивами, необходимо перед началом работы выделить память под такой массив, а после использования массива - освободить выделенную память:
{
Обязательно отключить проверку индексов,
иначе возникнет ошибка времени исполнения
}
{$R-}
Type
TType = Integer; { Или любой другой тип }
{ Указатель на динамический массив }
PDynArray = ^TDynArray;
TDynArray = array[1 .. 1] of TType;
Var
{ Через эту переменную будет осуществляться вся работа с массивом }
arr: PDynArray;
n, i: integer;
Begin
Write('n = '); ReadLn(n); { Вводится размер массива }
{
В "куче" запрашивается блок памяти с размером,
достаточным для хранения N элементов типа TType
}
GetMem(arr, n * SizeOf(TType));
(*** Начало работы с массивом ***)
{
Обращение к элементу динамического массива - почти такое же,
как и к элементу обычного (статического) массива,
за исключением операции "^" - разыменования ...
Пример:
}
For i := 1 To n Do arr^[i] := 2 * i;
For i := 1 To n Do
Write(arr^[i]:4);
(*** Закончили работу с массивом - уничтожаем его ***)
{ Возвращаем память назад в "кучу" }
FreeMem(arr, n * SizeOf(TType));
End.
Работа с динамическими матрицами
Для того, чтобы работать с динамическими матрицами, проще всего представить матрицу, как массив векторов (массив, содержащий указатели на строки матрицы). Перед началом работы с такой матрицей нужно сначала выделить память под массив указателей на строки, и только потом выделять память для хранения самих данных. После использования матрицы выделенная память освобождается в обратной последовательности:
{
Обязательно отключить проверку индексов,
иначе возникнет ошибка времени исполнения
}
{$R-}
Type
TType = Word; { Или любой другой тип }
Type
PVector = ^TVector;
{ Это - одна "строка" динамической матрицы }
TVector = Array[1 .. 1] of TType;
PDynMatrix = ^TDynMatrix;
{ Сама матрица - представляется как массив указателей на "строки" }
TDynMatrix = Array[1 .. 1] of PVector;
Var
{ Через эту переменную будет осуществляться вся работа с матрицей }
mxDynamic: PDynMatrix;
n, i, j: Word;
Begin
Write('n = '); ReadLn(n);
{ Выделяем память под указатели на "строки" }
GetMem(mxDynamic, n * SizeOf(PVector));
{ И для каждой "строки" - выделяем память для хранения данных }
For i := 1 To n Do
GetMem(mxDynamic^[i], n * SizeOf(TType));
(*** Работаем с матрицей ***)
{
Динамическая матрица представлена немного иначе,
чем динамический массив, поэтому для того, чтобы обратиться
к ее элементу, необходимы 2 операции разыменования указателей.
Пример:
}
For i := 1 To n Do { Строки }
For j := 1 To n Do { Столбцы (элементы строки) }
mxDynamic^[I]^[J]:=I*J;
For i := 1 To n Do Begin
WriteLn;
For j := 1 To n Do
Write(mxDynamic^[I]^[J]:4);
End;
(*** Закончили работу с матрицей - уничтожаем ее ***)
{ Освобождаем память в обратном порядке: }
{ Сначала - удаляем все "строки" }
For i := 1 To n Do
FreeMem(mxDynamic^[i], n * SizeOf(TType));
{ А теперь и указатели на них ... }
FreeMem(mxDynamic, n * SizeOf(PVector));
End.
Динамическая матрица с использованием функций ptr(), seg(), ofs() для получения указателя на нужное число.
const
n = 6;
type
PInt = ^integer;
var
i, j: integer;
PtrStr: array [1 .. n] of pointer;
pr: PInt;
begin
for i := 1 to n do
getmem(PtrStr[i], n*sizeof(Integer));
for i := 1 to n do
for j := 1 to n do begin
pr := Pint(ptr(seg(PtrStr[i]^), ofs(PtrStr[i]^)+(j-1)*sizeof(Integer)));
pr^ := i + j;
end;
for i := 1 to n do begin
writeln;
for j := 1 to n do begin
pr := PInt(ptr(seg(PtrStr[i]^), ofs(PtrStr[i]^)+(j-1)*sizeof(Integer)));
write(pr^:4);
end;
end;
for i := 1 to n do
freemem(PtrStr[i],n*sizeof(Integer));
end.