Структура для хранения неравномерной динамической матрицы?

78
11

Я хотел бы создать матричную структуру с неровными строками, как показано ниже:

[0] [0] 
[0] [0] [0]
[0] [0] [0] [0]
[0] [0] [0] [0] [0]
[0] [0] [0] [0]

Поэтому я хотел бы хранить где-то длину его столбца, а также ширину каждой строки. Моя реализация такова:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct {
size_t size;
int *data;
} dyn_row;

typedef struct {
size_t size;
dyn_row *row;
} dyn_matrix;

int main(void) {

int i, j;
dyn_matrix matrix;

srand(time(NULL));
// Allocate
matrix.size = 5;
matrix.row = malloc(matrix.size * sizeof(dyn_row));
for (i=0; i<matrix.size; i++) {
matrix.row[i].size = rand()%(i+1)+2;
matrix.row[i].data = malloc((matrix.row[i].size) * sizeof(int));
}
// Initialize
for (i=0; i<matrix.size; i++) {
for (j=0; j<matrix.row[i].size; j++) {
matrix.row[i].data[j] = 0;
}
}
// Print values & free
for (i=0; i<matrix.size; i++) {
for (j=0; j<matrix.row[i].size; j++) {
printf("[%d] ", matrix.row[i].data[j]);
}
printf("\n");
free(matrix.row[i].data);
}
free(matrix.row);

return 0;
}

Это хорошее решение? Какова оптимальная реализация для решения этой проблемы? Кроме того, является ли хорошей практикой вместо "int * data" писать "void * data", чтобы матрица могла хранить любые данные?

спросил(а) 2021-01-25T12:05:00+03:00 5 месяцев назад
1
Решение
64

Если вы знали, что то, что вы пытаетесь достичь, известно как "зубчатый массив", вы можете найти еще много примеров; хотя вы также обнаружите, что другие языки поддерживают эту структуру данных лучше.

Выделение данных - это тривиальная часть, но вам было бы полезно определить отдельные функции для распределения и доступа к массиву для безопасного переноса этих операций (проверка границ доступа, управление памятью и т.д.). Например, вы можете определить:

typedef dyn_matrix* tJaggedArray ;

// Create n rows of initially zero length
tJaggedArray jaggedCreate( int rows ) ;

// Set the length and allocate a row in array
tJaggedArray jaggedAllocRow( tJaggedArray array, int row, int length ) ;

// Get an array element, return true if element exists, else false
bool jaggedGet( tJaggedArray array, int row, int col, int* value ) ;

// Set an array element, return true if element exists, else false
bool jaggedSet( tJaggedArray array, int row, int col, int value ) ;

// Clean up array resources
void jaggedDestroy( tJaggedArray array ) ;

В C++ вы могли бы, конечно, обернуть это в классе, чтобы вам не пришлось передавать указатель массива на каждую функцию, и вы могли бы использовать шаблон для поддержки массивов разных типов, а перегрузка операторов для обеспечения доступа к массиву встроенный доступ к массиву. В С# проверка границ встроена в язык.

ответил(а) 2021-01-25T12:05:00+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема