定义矩阵相乘和转置的通用函数
前言
如果矩阵列数不固定,则不适宜用矩阵作为函数参数,这时可以使用指针(即一维数组)和行列数作为函数参数来定义通用的矩阵相乘和转置的函数。
一、定义矩阵相乘的通用函数
就不用文字分析了,直接上代码,在阅读理解代码这一过程中来体会将二维数组转为一维数组进行运算的好处。完整演示代码如下:
#include<iostream>
#include<iomanip>
using namespace std;
template<class T>
int matrix_mul(T A[], int ma, int na, T B[], int mb, int nb, T C[]) {
int i, j, k, u;
if(na!=mb) return 1;
for(i=0; i<ma; i++) {
for(j=0; j<nb; j++) {
u = nb*i + j;
for(k=0; k<na; k++) {
C[u] += A[na*i+k]*B[nb*k+j];
}
}
}
return 0;
}
template<class T>
void display_matrix(T A[], int m, int n) {
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
cout << setw(5) << A[i][j];
}
cout << endl;
}
}
int main() {
double a[4][5]={
{1.0, 3.0, -2.0, 0.0, 4.0},
{-2.0, -1.0, 5.0, -7.0, 2.0},
{0.0, 8.0, 4.0, 1.0, -5.0},
{3.0, -3.0, 2.0, -4.0, 1.0}
};
double b[5][3]={
{4.0, 5.0, -1.0},
{2.0, -2.0, 6.0},
{7.0, 8.0, 1.0},
{0.0, 3.0, -5.0},
{9.0, 8.0, -6.0}
};
double c[4][3]={0.0};
double d[4][3]={0.0};
cout << "Matrix C:" << endl;
display_matrix(c, 4, 3);
cout << "Matrix A:" << endl;
display_matrix(a, 4, 5);
cout << "Matrix B:" << endl;
display_matrix(b, 5, 3);
matrix_mul(a[0],4,5,b[0],5,3,c[0]);
cout << "Matrix C:" << endl;
display_matrix(c, 4, 3);
matrix_mul(&a[0][0],4,5, &b[0][0],5,3, &d[0][0]);
cout << "Matrix D:" << endl;
display_matrix(d, 4, 3);
return 0;
}
运行程序,输出如下:
Matrix C:
0 0 0
0 0 0
0 0 0
0 0 0
Matrix A:
1 3 -2 0 4
-2 -1 5 -7 2
0 8 4 1 -5
3 -3 2 -4 1
Matrix B:
4 5 -1
2 -2 6
7 8 1
0 3 -5
9 8 -6
Matrix C:
32 15 -9
43 27 24
-1 -21 77
29 33 -5
Matrix D:
32 15 -9
43 27 24
-1 -21 77
29 33 -5
二、定义矩阵转置的通用函数
同样直接上代码,通过阅读代码(以及注释)来理解函数的通用性达成途径。
完整演示代码如下:
#include<iostream>
#include<iomanip>
using namespace std;
template<class T>
int * transposeMatrix(T *array, int rows, int columns) {
//在堆区动态申请的内存,函数返回时申请的内存不会被释放掉
T *array_transposed = new T[rows*columns];
for(int j=0; j<columns; j++) {
for(int i=0; i<rows; i++) {
array_transposed[rows*j+i] = array[columns*(i%rows)+j];
}
}
return array_transposed;
}
template<class T>
void displayMatrix(T *array, int rows, int columns) {
for(int i=0; i<rows; i++) {
for(int j=0; j<columns; j++) {
cout << setw(7) << array[i*columns+j];
}
cout << endl;
}
}
int main() {
int rows, columns;
cout << "Please input the rows and columns of your Matrix:" << endl;
cin >> rows >> columns;
int array[rows*columns] = {0};
cout << "Please input the elements of your Matrix:" << endl;
for(int i=0; i<rows*columns; i++) {
cin >> array[i];
}
cout << "Original Matrix:" << endl;
displayMatrix(array, rows, columns);
int * array_transposed;
array_transposed = transposeMatrix(array, rows, columns);
cout << "Transposed Matrix:" << endl;
displayMatrix(array_transposed, columns, rows); //已完成行列互换
//在函数内部通过new动态创建的数组,记得使用完后将其delete掉
delete array_transposed;
return 0;
}
运行程序,输出如下:
Please input the rows and columns of your Matrix:
5 3
Please input the elements of your Matrix:
4 5 -1 2 -2 6 7 8 1 0 3 -5 9 8 -6
Original Matrix:
4 5 -1
2 -2 6
7 8 1
0 3 -5
9 8 -6
Transposed Matrix:
4 2 7 0 9
5 -2 8 3 8
-1 6 1 -5 -6
总结
以上代码中函数定义使用了C++中的模板函数声明语法,即使用template将函数定义为模板函数,其中的T为类型参数。
当T为double型时,transposeMatrix()函数可以实现实数矩阵的转置, matrix_mul()函数可以实现实数矩阵相乘。至于对于复数类型的矩阵,上面定义的函数还不能支持,因为复数的四则运算还需要定义专用的类来实现。但对于实数矩阵而言,这两个函数的通用性显然是毋庸置疑的。
transposeMatrix()函数使用了指针,且在函数内部使用new操作在堆区动态申请了内存,函数返回时申请的内存不会被释放掉,所以在申请的内存空间使用完毕后,要使用delete语句(例如:delete array_transposed;)手动释放掉,以能回收内存空间。如果觉得这样麻烦,也可以同matrix_mul()函数那样不使用指针,仅仅使用数组来实现。