注:操作较复杂,不建议写数值课设的同学借鉴
1. 定义矩阵结构体
矩阵是高等代数(线性代数)中的基本运算单位,在运算时具有一些特殊的性质。按定义来看,矩阵是由非质数(m × n)个基本元素单元组成,这些单元按一定的顺序排列,构成了一个m行n列的矩阵。
从定义中不难看出,定义矩阵的结构体需要包含三个数据成员:
- 行数(整型);
- 列数(整型);
- 各元素的值(根据计算精度需求进行调整).
于是定义矩阵结构体如下:
typedef struct Matrix{
int row;//行数
int col;//列数
value *M;
Matrix *AT;
}matrix;
其中, value是我自己定义的类型, 考虑到运算的需要, 使用long double类型:
typedef long double value;
除此之外,结构体中的结构体指针是指向该矩阵的转置,这是我为了后面编写算法方便设计的;而value* 类型的M是一个指向一个一位数组首元素地址的指针。
考虑到矩阵的大小应当是无限的,因此决定采用动态内存分配的方式给矩阵的各元素分配空间,虽然这样做矩阵的大小仍受限于内存空间的大小,但是比静态内存分配的方式在理论上更符合要求,实际场景下也能进行数据量更大的运算,比如图片处理、智能识别等。
2. 矩阵的创建
由于本人用MATLAB比较多,因此矩阵的创建方式我就照搬了MATLAB的方式:’ ’ or ‘,’ 输入某行的各元素;’;’ 换行。代码如下:
bool CreatMatrix(matrix *A) {
char operation;
int m = 0, n = 0;
int next = 0;
cout << "创建矩阵:" << endl;
A->M = (value *)malloc(sizeof(value));
cin >> *A->M;
operation = getchar();
while (operation != '\n') {
if (operation == ' ' || operation == ',') {
++next;
}
else if (operation == ';') {
if (n == 0) {
n = next;
}
else if (n > next) {
A->M = (value *)realloc(A->M, (m + 1) * (n + 1) * sizeof(value));
while (n != next) {
++next;
(A->M)[m * (n + 1) + next] = 0;
}
}
else if (n < next) {
cout << "矩阵大小有误!" << endl;
}
++m;
next = 0;
}
else {
cout << "输入有误!" << endl;
free(A->M);
return false;
}
A->M = (value *)realloc(A->M, (m * (n + 1) + next + 1) * sizeof(value));
cin >> (A->M)[m * (n + 1) + next];
operation = getchar();
}
if (m == 0) {
n = next;
}
else if (n > next) {
A->M = (value *)realloc(A->M, (m + 1) * (n + 1) * sizeof(value));
while (n != next) {
++next;
(A->M)[m * (n + 1) + next] = 0;
}
}
++m;
++n;
A->row = m;
A->col = n;
TransMatrix(A);
return true;
}
这里我为了偷懒,加入了一个自动补0的机制。
因为矩阵的行列数是根据输入的矩阵自动生成的,主要考虑了矩阵的合法性;而输入的合法性考虑的不是很多,若输入不合法在运算时可能会出错。
生成矩阵的情况比较多,因此代码写的有点丑。
TransMatrix是生成转置矩阵的操作,这个操作会在后面介绍。
最后这个函数是bool类型的,矩阵生成成功返回true,失败返回false。
3. 矩阵的初始化以及转置矩阵的生成
这两个算法之间其实没有太大的关系,之所以放一起只是因为它们的时间复杂度是一样的·····
初始化矩阵的代码如下,指向转置矩阵的指针初始化为空指针:
//生成 m × n 全 x