如果您想复制矩阵中的数据,无论是行还是列,都不能在少于 O(N) 的时间内完成,除非是小 N,硬件功能可能会有所帮助。
但是,如果您的矩阵是不可变的,您可以使用烟雾和镜子来产生具有单独列向量的错觉。
下面的代码直接输入到答案文本框中,甚至还没有编译。使用风险自负!
您的矩阵类型被定义为结构体:
typedef struct
{
unsigned int refCount; // how many Matrixes are referencing this data ref
size_t lineWidth; // number of doubles between element at row = n, col = 0 and row = n +1, col = 0
double* data; // the actual data
} DataRef;
typedef struct
{
size_t rows; // num rows in matrix
size_t cols; // num cols in matrix
size_t dataOffset; // offset in doubles from the start of data of element at row = 0, col = 0
DataRef* data;
} Matrix;
创建一个全新的矩阵(我省略了所有错误处理以使其更简单)。
Matrix* matrix_create(size_t rows, size_t cols, const double* values)
{
Matrix* ret = calloc(1, sizeof *ret);
ret->rows = rows;
ret->cols = cols;
ret->dataOffset = 0;
ret->data = calloc(1, sizeof *dataRef);
ret->data->lineWidth = cols;
ret->data->data = allocateAndCopy(rows * cols, values); // mallocs a new block of doubles big enough for the values
ret->data->refCount = 1;
return ret;
}
访问一个元素(同样没有错误处理,例如边界错误)
double matrix_elementAt(Matrix* matrix, size_t row, size_t col)
{
size_t offset = matrix->dataOffset + row * matrix->data->lineWidth + col;
return *(matrix->data->data + offset);
}
从另一个矩阵的矩形区域创建一个新矩阵(同样,需要错误处理)
Matrix* matrix_createFromRegion(Matrix* old, size_t startRow, size_t startCol, size_t rows, size_t cols)
{
Matrix* ret = calloc(1, sizeof *ret);
ret->rows = rows;
ret->cols = cols;
ret->dataOffset = old->dataOffset + startRow * old->dataLineWidth + startCol;
ret->data = old->data;
ret->data->refCount++;
return ret;
}
从另一个矩阵中的列创建一个新矩阵:
Matrix* vector = matrix_createFromRegion(aMatrix, 0, colYouWant, matrix_numRows(aMatrix), 1);
释放矩阵
void matrix_free(Matrix* aMatrix)
{
if (aMatrix->data->refCount == 1)
{
free(aMatrix->data->data);
free(aMatrix->data);
}
else
{
aMatrix->data->refCount--;
}
free(aMatrix);
}
如果你想要可变矩阵,任何时候你修改一个元素,检查 refCount,如果它大于 1,在修改它之前复制 DataRef(减少旧 dataRef 上的 refCount),否则修改 dataRef。
现在上面使用了大量的 malloc,因此可能比小矩阵的简单实现效率低。但是,您可以维护未使用的 DataRef 结构和 Matrix 结构的列表,而不是在完成后释放它们,而是将它们放在空闲列表中。分配新结构时,从空闲列表中获取结构,除非它们为空。这样,获取表示现有矩阵的一列的矩阵通常需要固定时间。