Получить все нулевые элементы выше главной диагонали матрицы - C (СИ)
Формулировка задачи:
Дана матрица целых чисел. Собрать все нулевые элементы выше
главной диагонали (заполнение осуществлять параллельно главной диагонали).
Решение задачи: «Получить все нулевые элементы выше главной диагонали матрицы»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void PrintArr(const int* const a, const size_t N)
{
size_t i = 0;
printf("===== Array: =====\n");
for (i = 0; i < N; i++)
{
printf("%d ", a[i]);
}
printf("\n");
printf("==================\n");
}
size_t GetElementCountAboveMainDiag(const size_t m, const size_t n)
{
size_t count = 0;
if (m < n)
{
count = ((2 * n - m - 1) * m) / 2;
}
else
{
count = ((1 + m - 1) * m) / 2;
}
return count;
}
void ParallelScan(const int** const a, const size_t M, const size_t N, int* const top)
{
size_t diagonalIndex = 0;
size_t i = 0;
size_t j = 0;
size_t k = 0;
size_t offset = 0;
size_t minSize = 0;
if (M > N)
{
minSize = N;
}
else
{
minSize = M;
}
/* scanning parallel to main diagonal */
k = 0;
for (diagonalIndex = 1; diagonalIndex < N; diagonalIndex++)
{
if (N - diagonalIndex < minSize)
{
offset++;
}
for (i = 0; i < minSize - offset; i++)
{
j = diagonalIndex + i;
top[k] = a[i][j];
k++;
}
}
}
void ParallelWrite(int** const a, const size_t M, const size_t N, const int* const top)
{
size_t diagonalIndex = 0;
size_t i = 0;
size_t j = 0;
size_t k = 0;
size_t offset = 0;
size_t minSize = 0;
if (M > N)
{
minSize = N;
}
else
{
minSize = M;
}
/* scanning parallel to main diagonal */
k = 0;
for (diagonalIndex = 1; diagonalIndex < N; diagonalIndex++)
{
if (N - diagonalIndex < minSize)
{
offset++;
}
for (i = 0; i < minSize - offset; i++)
{
j = diagonalIndex + i;
a[i][j] = top[k];
k++;
}
}
}
int FindFirstNonZero(const int* const a, const size_t N, size_t* const nonZeroIndexPtr)
{
size_t i = 0;
while (i < N)
{
if (a[i] != 0)
{
(*nonZeroIndexPtr) = i;
return 1;
}
i++;
}
return 0;
}
int SettleTop(int** const a, const size_t M, const size_t N)
{
int errorCode = 0;
int* topArray = NULL;
size_t i = 0;
size_t k = 0;
size_t topArrayLength = 0;
topArrayLength = GetElementCountAboveMainDiag(M, N);
topArray = malloc(topArrayLength * sizeof(*topArray));
if (topArray == NULL)
{
errorCode = 1;
}
else
{
ParallelScan(a, M, N, topArray);
/*
now we settle zeroes in array, moving all to left side
*/
/* step 1: skip all that may be already on left side (search for starting fill position) */
if (FindFirstNonZero(topArray, topArrayLength, &k))
{
/* step 2: moving all zeroes to left */
for (i = k; i < topArrayLength; i++)
{
if (topArray[i] == 0)
{
topArray[i] = topArray[k];
topArray[k] = 0;
k++;
}
}
/* now elements are settled, exporting top */
ParallelWrite(a, M, N, topArray);
}
}
free(topArray);
return errorCode;
}
int ClearBottom(int** const a, const size_t M, const size_t N)
{
int errorCode = 0;
int* topArray = NULL;
size_t i = 0;
size_t j = 0;
size_t k = 0;
size_t topArrayLength = 0;
topArrayLength = GetElementCountAboveMainDiag(M, N);
topArray = malloc(topArrayLength * sizeof(*topArray));
if (topArray == NULL)
{
errorCode = 1;
}
else
{
/* parallel copy of elements */
ParallelScan(a, M, N, topArray);
/* skip all that may be already on left side (search for starting fill position) */
if (FindFirstNonZero(topArray, topArrayLength, &k))
{
/* scanning below diagonal (inclusive) and move zeros */
for (i = 0; i < M; i++)
{
for (j = 0; j < i + 1; j++)
{
if (a[i][j] == 0)
{
a[i][j] = topArray[k];
topArray[k] = 0;
k++;
}
}
}
/* exporting top */
ParallelWrite(a, M, N, topArray);
}
}
free(topArray);
return errorCode;
}
void CreateAndGenerateMatrix(int*** const matrixPtr, size_t* const rowCountPtr, size_t* const colCountPtr)
{
int** a = NULL;
size_t m = 0;
size_t n = 0;
size_t i = 0;
size_t j = 0;
m = rand() % 11 + 1;
n = rand() % 11 + 1;
a = malloc(m * sizeof(*a));
for (i = 0; i < m; i++)
{
a[i] = malloc(n * sizeof(**a));
}
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
a[i][j] = rand() % 10;
}
}
(*matrixPtr) = a;
(*rowCountPtr) = m;
(*colCountPtr) = n;
}
void PrintMatrix(const int** const a, const size_t M, const size_t N)
{
size_t i = 0;
size_t j = 0;
printf("===============\n");
for (i = 0; i < M; i++)
{
for (j = 0; j < N; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("===============\n");
}
void FreeMatrix(int*** const matrixPtr, size_t* const rowCountPtr, size_t* const colCountPtr)
{
size_t i = 0;
for (i = 0; i < (*rowCountPtr); i++)
{
free((*matrixPtr)[i]);
(*matrixPtr)[i] = NULL;
}
free(*matrixPtr);
(*matrixPtr) = NULL;
(*rowCountPtr) = 0;
(*colCountPtr) = 0;
}
int main(void)
{
int** a = NULL;
size_t m = 0;
size_t n = 0;
srand(time(NULL));
CreateAndGenerateMatrix(&a, &m, &n);
PrintMatrix(a, m, n);
SettleTop(a, m, n);
ClearBottom(a, m, n);
PrintMatrix(a, m, n);
FreeMatrix(&a, &m, &n);
return 0;
}
Объяснение кода листинга программы
Код представляет собой функцию main, которая генерирует случайную матрицу размером m x n и выводит ее на экран. Затем он использует две функции ParallelScan и ParallelWrite, чтобы заполнить верхнюю диагональ матрицы нулями, сначала слева направо, а затем сверху вниз. Функция FindFirstNonZero используется для поиска первого ненулевого элемента в верхнем массиве, а функция ClearBottom для очистки нижней части матрицы, перемещая все нули влево. Наконец, матрица выводится на экран еще раз, и функция FreeMatrix освобождает память, выделенную для матрицы.