大家好,我是一位编程初学者,请多多关照
程序代码:#include<stdio.h>
#include<math.h>
#define DOUBLE_LIMIT 1.0E-300
typedef struct matrix_element_node
{
double data;
int col;
struct matrix_element_node * next;
}MATRIX_ELEMENT;
typedef struct matrix
{
MATRIX_ELEMENT * r;
int rows;
int columns;
}MATRIX;
MATRIX * Matrix_create(int rows, int columns);//创建rows行columns列矩阵,元素初始值为0
void Matrix_free(MATRIX * mat);//销毁mat矩阵
int Matrix_rows_len(MATRIX * mat);//获取矩阵mat的行数,mat为空指针时返回0
int Matrix_cols_len(MATRIX * mat);//获取矩阵mat的列数,mat为空指针时返回0
int Matrix_set(MATRIX * mat, int row, int column, double value);//设置mat矩阵第row行第column列的元素值为value,操作成功返回0,否则返回一个非0值
double Matrix_get(MATRIX * mat, int row, int column);//获取mat矩阵第row行第column列的元素值
MATRIX * Matrix_add(MATRIX * mat1, MATRIX * mat2);//计算两个矩阵相加,返回和矩阵。当两个矩阵不能作加法运算时返回NULL
MATRIX * Matrix_mul(MATRIX * mat1, MATRIX * mat2);//计算两个矩阵相乘,注意是mat1左乘mat2。如果不能作乘法运算返回NULL
MATRIX * Matrix_mul_real(MATRIX * mat, double a);//计算矩阵与实数相乘
MATRIX * Matrix_dot_mul(MATRIX * mat1, MATRIX * mat2);//计算两个矩阵的点乘。如果不能作运算返回NULL
MATRIX * Matrix_trans(MATRIX * mat);//返回mat的转置矩阵
void Matrix_print(MATRIX * mat);
int main()
{
MATRIX * a, * b, * c;
int i, j;
a = Matrix_create(3, 3);
b = Matrix_create(3, 3);
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++)
{
Matrix_set(a, i, j, i * 3 + j + 1);
Matrix_set(b, i, j, 9 - i * 3 - j);
}
printf("a = \n");
Matrix_print(a);
printf("b = \n");
Matrix_print(b);
printf("a + b = \n");
c = Matrix_add(a, b);
Matrix_print(c);
printf("a * b = \n");
Matrix_free(c);
c = Matrix_mul(a, b);
Matrix_print(c);
printf("a * 2.5 = \n");
Matrix_free(c);
c = Matrix_mul_real(a, 2.5);
Matrix_print(c);
printf("a .* b = \n");
Matrix_free(c);
c = Matrix_dot_mul(a, b);
Matrix_print(c);
printf("a' = \n");
Matrix_free(c);
c = Matrix_trans(a);
Matrix_print(c);
Matrix_free(a);
Matrix_free(b);
Matrix_free(c);
return 0;
}
MATRIX * Matrix_create(int rows, int columns)
{
MATRIX * p;
int i;
p = (MATRIX *)malloc(sizeof(MATRIX));
p->r = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT) * rows);
for(i = 0; i < rows; p->r[i++].next = NULL);
p->rows = rows;
p->columns = columns;
return p;
}
void Matrix_free(MATRIX * mat)
{
MATRIX_ELEMENT * e, * t;
int i;
for(i = 0; i < mat->rows; i++)
for(e = mat->r[i].next; e != NULL; free(t)) t = e, e = e->next;
free(mat->r);
free(mat);
}
int Matrix_rows_len(MATRIX * mat)
{
return mat->rows;
}
int Matrix_cols_len(MATRIX * mat)
{
return mat->columns;
}
int Matrix_set(MATRIX * mat, int row, int column, double value)
{
MATRIX_ELEMENT * pre, * e, * t;
if(mat == NULL || row < 0 || row >= mat->rows || column < 0 || column >= mat->columns) return 1;
for(pre = &(mat->r[row]), e = pre->next; e != NULL && e->col < column; pre = e, e = e->next);
if(fabs(value) < DOUBLE_LIMIT)
{
if(e != NULL && e->col == column)
{
pre = e->next;
free(e);
}
}
else
{
if(e != NULL && e->col == column)
{
e->data = value;
}
else
{
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = value;
t->col = column;
t->next = e;
pre->next = t;
}
}
return 0;
}
double Matrix_get(MATRIX * mat, int row, int column)
{
MATRIX_ELEMENT * e;
if(mat == NULL) return 0;
for(e = mat->r[row].next; e != NULL && e->col < column; e = e->next);
return (e != NULL && e->col == column) ? e->data : 0;
}
MATRIX * Matrix_add(MATRIX * mat1, MATRIX * mat2)
{
MATRIX * mat;
MATRIX_ELEMENT * pre, * e1, * e2, * e, * t;
double value;
int col, i;
if(mat1 == NULL || mat2 == NULL || mat1->rows != mat2->rows || mat1->columns != mat2->columns) return NULL;
mat = Matrix_create(mat1->rows, mat1->columns);
for(i = 0; i < mat->rows; i++)
{
e1 = mat1->r[i].next;
e2 = mat2->r[i].next;
pre = &(mat->r[i]);
while(e1 != NULL && e2 != NULL)
{
if(e1->col < e2->col)
{
value = e1->data;
col = e1->col;
e1 = e1->next;
}
else if(e1->col > e2->col)
{
value = e2->data;
col = e2->col;
e2 = e2->next;
}
else
{
value = e1->data + e2->data;
col = e1->col;
e1 = e1->next;
e2 = e2->next;
if(fabs(value) < DOUBLE_LIMIT) continue;
}
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = value;
t->col = col;
pre->next = t;
pre = t;
}
for(e = (e1 != NULL) ? e1 : e2; e != NULL; e = e->next)
{
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = e->data;
t->col = e->col;
pre->next = t;
pre = t;
}
pre->next = NULL;
}
return mat;
}
MATRIX * Matrix_mul(MATRIX * mat1, MATRIX * mat2)
{
MATRIX * mat;
MATRIX_ELEMENT ** pre; //mat矩阵的列元素指针数组,每个元素指向每行的最后一个元素结点
MATRIX_ELEMENT * mr; //mat1矩阵的行指针,指向mat1的计算行的结点
MATRIX_ELEMENT **mc; //mat2矩阵的列元素指针数组,每个元素指向mat2的计算列的结点
MATRIX_ELEMENT *t; //临时指针,用于分配新申请的结点内存
int i, j, count; //count为mat2待计算列中的结点数量
double value;
if(mat1 == NULL || mat2 == NULL || mat1->columns != mat2->rows) return NULL;
mat = Matrix_create(mat1->rows, mat2->columns);
pre = (MATRIX_ELEMENT **)malloc(sizeof(MATRIX_ELEMENT *) * mat->rows);
mc = (MATRIX_ELEMENT **)malloc(sizeof(MATRIX_ELEMENT *) * mat2->rows);
for(count = i = 0; i < mat2->rows; i++)
if((mc[i] = mat2->r[i].next) != NULL) count++;
if(count == 0)
{
free(pre);
free(mc);
return mat;
}
for(i = 0; i < mat->rows; i++) pre[i] = &(mat->r[i]);
//计算过程是按列优先进行的
//举例说明:矩阵下标从0开始计数
//一般的计算习惯是按行优先的,如先计算[0,0],[0,1],[0,2]...,再计算[1,0],[1,1],[1,2]...
//这里的计算过程是先计算[0,0],[1,0],[2,0]...,再计算[0,1],[1,1],[2,1]...
//选择这种计算顺序是为了减少计算过程中对mat2矩阵元素检索所需要的指针移动次数,提高计算效率
for(j = 0; count > 0 && j < mat->columns; j++)
{
for(i = 0; i < mat->rows; i++)
{
value = 0;
for(mr = mat1->r[i].next; mr != NULL; mr = mr->next)
if(mc[mr->col] != NULL && mc[mr->col]->col == j)
value += mr->data * mc[mr->col]->data;
if(fabs(value) < DOUBLE_LIMIT) continue;
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = value;
t->col = j;
t->next = NULL;
pre[i]->next = t;
pre[i] = t;
}
for(i = 0; i < mat2->rows; i++)
{
if(mc[i] == NULL) continue;
if(mc[i]->col <= j) mc[i] = mc[i]->next;
if(mc[i] == NULL) count--;
}
}
free(pre);
free(mc);
return mat;
}
MATRIX * Matrix_mul_real(MATRIX * mat, double a)
{
MATRIX * new_mat;
MATRIX_ELEMENT * pre, * e, * t;
double value;
int i;
if(mat == NULL) return NULL;
new_mat = Matrix_create(mat->rows, mat->columns);
for(i = 0; i < mat->rows; i++)
for(pre = &(new_mat->r[i]), e = mat->r[i].next; e != NULL; e = e->next)
{
value = e->data * a;
if(fabs(value) < DOUBLE_LIMIT) continue;
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = value;
t->col = e->col;
t->next = NULL;
pre->next = t;
pre = t;
}
return new_mat;
}
MATRIX * Matrix_dot_mul(MATRIX * mat1, MATRIX * mat2)
{
MATRIX * mat;
MATRIX_ELEMENT * pre, * e1, * e2, * t;
double value;
int i;
if(mat1 == NULL || mat2 == NULL || mat1->rows != mat2->rows || mat1->columns != mat2->columns) return NULL;
mat = Matrix_create(mat1->rows, mat1->columns);
for(i = 0; i < mat->rows; i++)
{
pre = &(mat->r[i]);
e1 = mat1->r[i].next;
e2 = mat2->r[i].next;
while(e1 != NULL && e2 != NULL)
{
if(e1->col < e2->col){ e1 = e1->next; continue;}
if(e1->col > e2->col){ e2 = e2->next; continue;}
value = e1->data * e2->data;
if(fabs(value) < DOUBLE_LIMIT) continue;
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = value;
t->col = e1->col;
pre->next = t;
pre = t;
e1 = e1->next;
e2 = e2->next;
}
pre->next = NULL;
}
return mat;
}
MATRIX * Matrix_trans(MATRIX * mat)
{
MATRIX * new_mat;
MATRIX_ELEMENT ** pre, * e, * t;
int i;
if(mat == NULL) return NULL;
new_mat = Matrix_create(mat->columns, mat->rows);
pre = (MATRIX_ELEMENT **)malloc(sizeof(MATRIX_ELEMENT *) * new_mat->rows);
for(i = 0; i < new_mat->rows; i++) pre[i] = &(new_mat->r[i]);
for(i = 0; i < mat->rows; i++)
for(e = mat->r[i].next; e != NULL; e = e->next)
{
t = (MATRIX_ELEMENT *)malloc(sizeof(MATRIX_ELEMENT));
t->data = e->data;
t->col = i;
t->next = NULL;
pre[e->col]->next = t;
pre[e->col] = t;
}
free(pre);
return new_mat;
}
void Matrix_print(MATRIX * mat)
{
MATRIX_ELEMENT * e;
int i, j;
for(i = 0; i < mat->rows; i++, puts("\n"))
for(j = 0; j < mat->columns; j++)
printf("%10.2f", Matrix_get(mat, i, j));
}
