大家好,我是一位编程初学者,请多多关照
#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)); }