48466 (Работа с двумерными числовыми массивами), страница 2
Описание файла
Документ из архива "Работа с двумерными числовыми массивами", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "курсовые/домашние работы", в предмете "информатика, программирование" в общих файлах.
Онлайн просмотр документа "48466"
Текст 2 страницы из документа "48466"
Далее функция CircuarShift, осуществляющая циклический сдвиг строк матрицы вверх, или вниз. Направление сдвига определяется булевым параметром shiftUp, передаваемым процедуре:
-
{
-
осуществляет циклический сдвиг строк матрицы arr вверх при shiftUp = true,
-
и вниз, при shiftUp = false
-
}
-
procedure CircuarShift(var arr: TMatrix; shiftUp: boolean);
-
var
-
RowN: integer;
-
tmpRow: TVector;//временная переменная для хранения строки иатрицы
-
begin
-
if high(arr) < 1 then exit;//если в матрице меньше двух строк - выходим
-
if shiftUp then
-
begin//если сдвиг вверх
-
tmpRow:= arr[high(arr)];//сохраним последнюю строку матрицы
-
arr[high(arr)]:= arr[0];//приравняем последнюю строку первой
-
for rowN:= 0 to high(arr)-2 do
-
begin//для строк с нулевой по пред-предпоследнюю
-
arr[rowN]:= arr[rowN+1];//текущая строка равна нижней
-
end;
-
arr[high(arr)-1]:= tmpRow;//предпоследнюю строку приравняем последней
-
end
-
else
-
begin//иначе, если сдвиг вниз
-
tmpRow:= arr[0];//сохраним нулвую строку
-
arr[0]:= arr[high(arr)];//приравняем нулевую строку последней
-
for rowN:= high(arr) downto 2 do
-
begin//для строк с последней по вторую
-
arr[RowN]:= arr[RowN-1];//текущая строка равна верхней
-
end;
-
arr[1]:= tmpRow;//первую строку приравняем нулевой
-
end;
-
end;
«Разворачивание» матрицы
Процедура UnwindMatrix осуществляет "разворачивание" матрицы в одномерный массив против часовой стрелки. Эта процедура в своих локальных переменных хранит координаты текущего элемента, текущее направление обхода (посредством перечислимого типа TDirection), а так же границы ещё не обойдённой части матрицы, которые сужаются каждый раз, когда проходится целая строка, или столбец. В этот же момент меняется направление обхода и текущим становится элемент в этом направлении. Обход завершается, когда число пройденных элементов станет равняться количеству элементов в матрице:
-
//перечисление - направления
-
type TDirection = (down, right, up, left);
-
{обходит матрицу arr против часовой стрелки и наполняет элементами массив res}
-
procedure UnwindMatrix(const arr: TMatrix; var res: TVector);
-
var
-
count, cur: integer;//число элементов в матрице и счётчик элементов
-
RowN, ColN: integer;
-
leftB, bottomB, rightB, topB: integer;//границы обхода - меняются при проходе полной строки или столбца
-
direction: TDirection;//текущее направление обхода
-
begin
-
if (length(arr) = 0) or (length(arr[0]) = 0) then exit;//если в матрице нет элементов - выходим
-
count:= length(arr) * length(arr[0]);//подсчитаем число элементов в матрице
-
SetLength(res, count);//выделим память для хранения всех элементов матрицы
-
//начальные условия обхода: текущий элемент [0,0], границы совпадают с граниуцами матриы, направление - вниз
-
direction:= down;
-
RowN:= 0;
-
ColN:= 0;
-
leftB:= 0;
-
bottomB:= high(arr);
-
rightB:= high(arr[0]);
-
topB:= 0;
-
for cur:= 0 to count-1 do
-
begin//пока не пройдём count элементов
-
res[cur]:= arr[RowN, ColN];//добавляем текущий элемент в массив
-
//дальненйшие действия зависят от текущего направления обхода
-
case direction of
-
down://если вниз
-
if RowN < bottomB then inc(RowN)//если не дошли до нижней границы - сдвигаемся вниз
-
else
-
begin//иначе - прошли левый столбец
-
direction:= right;//сменим направление на "вправо"
-
inc(leftB);//сдвинем левую границу к центру
-
inc(ColN);//сдвинемся вправо
-
end;
-
right://если вправо
-
if ColN < rightB then inc(ColN)//если не дошли до правой границы - сдвигаемся вправо
-
else
-
begin//иначе - прошли нижнюю строку
-
direction:= up;//сменим направление на "вверх"
-
dec(bottomB);//сдвинем нижнюю границу к центру
-
dec(RowN);//сдвинемся вверх
-
end;
-
up://если вверх
-
if RowN > topB then dec(RowN)//если не дошли до верхней границы - сдвигаемся вверх
-
else
-
begin//иначе - прошли правый столбец
-
direction:= left;//сменим направление на "влево"
-
dec(rightB);//сдвинем правую границу к центру
-
dec(ColN);//сдвинемся влево
-
end;
-
left://если влево
-
if ColN > leftB then dec(ColN)//если не дошли до левой границы - сдвигаемся влево
-
else
-
begin//иначе - прошли верхнюю строку
-
direction:= down;//сменим направление на "вниз"
-
inc(topB);//сдвинем верхнюю границу к центру
-
inc(RowN);//сдвинемся вниз
-
end;
-
end;
-
end;
-
end;
Сортировка строк матрицы
Наконец упорядочивание строк матрицы по убыванию суммы элементов каждой строки. Вспомогательная функция getRowSum возвращает сумму элементов заданной строки:
-
{возвращает сумму элементов RowN-ой строки матрицы arr}
-
function getRowSum(const arr: TMatrix; RowN: integer): Int64;
-
var ColN: integer;
-
begin
-
Result:= 0;
-
if RowN > high(arr) then exit;//если в матрице нет RowN-ой строки - выходим
-
for ColN:= 0 to high(arr[RowN]) do//суммируем элементы строки
-
Result:= Result + arr[RowN, ColN];
-
end;
Сама сортировка осуществляется посредством процедуры SortRows. Был выбран алгоритм прямой вставки, так как число строк в матрице не предполагается большим, а этот алгоритм эффективен на небольших наборах данных. В любом случае сортировка осуществляется быстро, так как при перемене мест строк не происходит копирование данных, но просто переставляются местами указатели. Листинг этой функции:
-
{сортирует строки матрицы по убыванию сумм элементов каждой строки}
-
procedure SortRows(var arr: TMatrix);
-
var
-
i, k: integer;//переменные для алгоритма сортировки
-
tmpRow: TVector;//временная переменная для алгоритма сортировки
-
begin
-
//алгоритм сортировки методом прямой вставки
-
for i:= 1 to high(arr) do
-
begin//для строк с первой по последнюю
-
k:= i;//начиная с текущей строки
-
while (k > 0) and (getRowSum(arr, k) > getRowSum(arr, k-1)) do
-
begin//пока не дошли до нулевой строки, и сумма строки над текущей строкой больше текущей суммы
-
swap(arr[k-1], arr[k]);//поменяем текущую строку и строку над ней местами
-
dec(k);//сдвинемся вверх
-
end;
-
end;
-
end;
2.3.2 Модуль fileIO
Этот модуль содержит процедуры для файлового ввода/вывода матриц. Используются текстовые файлы, которые предварительно необходимо открыть и подготовить к чтению/записи.
Формат файла, содержащего матрицу таков: матрица записана построчно, начиная с первой строки, элементы в каждой строке записаны слева направо и разделены произвольным количеством пробелов. Именно такой файл создаёт процедура Write2DArray:
-
{
-
записывает матрицу arr в текстовый файл outFile. Файл должен быть
-
предварительно открыт
-
}
-
procedure Write2DArray(const arr: TMatrix; const outFile: TextFile);
-
var
-
rowN, colN: integer;
-
begin
-
for rowN:= low(arr) to high(arr) do
-
begin
-
for colN:= low(arr[rowN]) to high(arr[rowN]) do
-
begin
-
//ширина поля 12, так как -2147483648 - 11 символов
-
Write(outFile, arr[rowN, colN]: 12);
-
end;
-
Writeln(outFile);
-
end;
-
end;
Процедура Read2DArray читает файл по строкам, разбирая каждую строку на подстрока пробелами с помощью процедуры ExtractStrings:
-
{ читает матрицу arr из текстового файла inFile. Файл должен быть
-
предварительно открыт}
-
procedure Read2DArray(var arr: TMatrix; const inFile: TextFile);
-
var
-
rowN, colN: integer;
-
colCount: integer; //максимальное количество чисел в строке (число столбцов матрицы)
-
lineStr: string; //текущая строка
-
strNumbers: TStringList;//текущая строка, разделённая на подстроки пробелами
-
begin
-
rowN:= 0;
-
colCount:= 0;
-
strNumbers:= TStringList.Create;
-
arr:= nil;
-
while not Eof(inFile) do
-
begin
-
Readln(inFile, lineStr);
-
strNumbers.Clear;
-
ExtractStrings([' '], [], PChar(lineStr), strNumbers); //разделим пробелами на подстроки
-
if colCount < strNumbers.Count then colCount:= strNumbers.Count;
-
SetLength(arr, rowN+1, colCount);//выделим память под новую строку
-
for colN:= 0 to strNumbers.Count-1 do //для каждого числа в строке
-
arr[rowN, colN]:= StrToIntDef(strNumbers[colN], 0);
-
Inc(rowN);
-
end;
-
strNumbers.Destroy;
-
end;
2.3.3 Модуль form
Модуль, содержащий форму, переменную для хранения исходной матрицы, процедуры синхронизации содержания матрицы и элементов формы, а так же процедуру задания размеров матрицы.
Так как задача чётко разделена на задания, оперирующие одними и теми же исходными данными (целочисленным двумерным массивом), было принято решение разделить интерфейс приложения на две части. В верхней части формы отображается матрица исходных данных, которую можно редактировать и размеры которой можно менять. Нижняя часть формы представляет собой набор закладок, каждая из которых соответствует одной из поставленных задач. На каждой закладке содержится описание задания, кнопка «выполнить», а так же элементы, необходимы для отображения результата в рамках этого задания. Некоторые задания состоят в изменении исходной матрицы, результат выполнения таких заданий отображается непосредственно в исходных данных в верхней части формы. Всего существует как минимум три способа выбрать задачу: щёлкнуть мышкой по закладке, выбрать нужный пункт в меню «Задачи», нажать одну из кнопок F1 - F5.
Опишем важные процедуры формы. Процедура ReadMatrix осуществляет чтение исходных данных из таблицы на форме в двумерный массив. Перед началом чтения процедура устанавливает размер массива:
-
{заполнить матрицу в соответствии с содержанием таблицы на форме}
-
procedure TMainForm.ReadMatrix;
-
var rowN, colN: integer;
-
begin
-
SetLength(workMatrix, G_Matrix.RowCount-1, G_Matrix.ColCount-1);
-
for rowN:= 0 to G_Matrix.RowCount-2 do
-
for colN:= 0 to G_Matrix.ColCount-2 do
-
workMatrix[rowN, colN]:= StrToIntDef(G_Matrix.Cells[colN+1, rowN+1], 0);
-
end;
Процедура writeMatrix осуществляет обратную операцию, она заполняет поля таблицы в соответствии с массивом. Кроме этого она меняет значения числа строк и столбцов в соответствии с размерами массива:
-
{заполнить таблицу на форме в соответствии с содержанием матрицы}
-
procedure TMainForm.writeMatrix;
-
var rowN, colN: integer;
-
begin
-
G_Matrix.Cells[1, 1]:= '';//если матрица пуста
-
E_RowsN.Text:= IntToStr(high(workMatrix) + 1);
-
if(E_RowsN.Text <> '0') then
-
E_ColsN.Text:= IntToStr(high(workMatrix[low(workMatrix)]) + 1)
-
else E_ColsN.Text:= '0';
-
B_SetDimmsClick(self);
-
//заполним таблицу
-
for rowN:= low(workMatrix) to high(workMatrix) do
-
for colN:= low(workMatrix[rowN]) to high(workMatrix[rowN]) do
-
G_Matrix.Cells[colN+1, rowN+1]:= IntToStr(workMatrix[rowN, colN]);
-
end;
Процедура B_SetDimmsClick является обработчиком нажатия кнопки «задать размеры». Она проверяет, не стали ли размеры меньше единицы, меняет число строк и столбцов в таблицах формы, а так же проставляет номера строк и столбцов:
-
{обраюотчик уствновки размеров матрицы}
-
procedure TMainForm.B_SetDimmsClick(Sender: TObject);
-
var
-
i: integer;
-
RowsN, ColsN: integer;
-
begin
-
//значения размеров не должны быть меньше 1
-
RowsN:= StrToIntDef(E_RowsN.Text, 0);
-
if RowsN < 1 then begin RowsN:= 1; E_RowsN.Text:= '1' end;
-
ColsN:= StrToIntDef(E_ColsN.Text, 0);
-
if ColsN < 1 then begin ColsN:= 1; E_ColsN.Text:= '1' end;
-
//число строк и столбцов в таблице, учитывая колонку и строку с номерами
-
G_Matrix.RowCount:= RowsN + 1;
-
G_Matrix.ColCount:= ColsN + 1;
-
//в этих таблицах отображаются одномерные массивы из первого задания
-
G_Task1B.RowCount:= RowsN;
-
G_Task1C.RowCount:= RowsN;
-
//одномерный массив из четвёртого задания имеет длину, равную числу элементов исходной матрицы
-
G_Task4.ColCount:= RowsN * ColsN;
-
//расставим номера строк и столбцов
-
for i:= 0 to RowsN do
-
begin
-
G_Matrix.Cells[0, i+1]:= IntToStr(i+1);
-
G_Task1B.Cells[0, i]:= IntToStr(i+1);
-
G_Task1C.Cells[0, i]:= IntToStr(i+1);
-
end;
-
for i:= 0 to ColsN do
-
G_Matrix.Cells[i+1, 0]:= IntToStr(i+1);
-
for i:= 0 to RowsN * ColsN do
-
G_Task4.Cells[i, 0]:= IntToStr(i+1);
-
G_Matrix.Refresh;
-
end;
Процедура FormDestroy выполняется при уничтожении формы и выполняет очень важную функцию – освобождает память, которая выделялась во время работы приложения под матрицу исходных данных.