使用三元组实现稀疏矩阵的建立、逆转、乘法。
乘法没有使用附加向量,是自己想得。有错误请谅解。性能可能没有书上介绍的好。
代码如下:(本代码只经过本人的简单测试,可能存在问题。请相信自己的能力,敢于质疑。欢迎提供更好的、更快、更简洁的代码或者方法和指出错误。在ubuntu12.04使用gcc4.6.3版本编译,在vc中如出现错误,请谅解。)
/* *created by Reage at 2012 November 29 *description: 稀疏矩阵实现,包含乘法、逆转 * *blog:http://blog.csdn.net/rentiansheng */ #include <stdio.h> #include <stdlib.h> #define LINE print_split(20) typedef struct triple{ int i,j;//行列 int value; }triple; typedef struct matrix{ triple * head; int row,column,count;//矩阵的行、列、稀疏矩阵的元素个数 }matrix; /* *description:判断某一个位置是否已经存在元素 *parameter: * x:行坐标 * y:列坐标 * count:要查找的元素个数,如果为0表示全部,否则是count的值 *result:找到返回1,未找到返回0 */ int find_ item (matrix *m, int x, int y, int count ){ triple *tp = m->head; if ( !count || count > m->count ) count =m->count; int i; for (i = 0; i < count - 1; i++){ if ( tp->i == x && tp->j == y) return 1; tp++; } return 0; } /* *初始化稀疏矩阵 */ void init_matrix (matrix *m, int row, int column, int count){ // if (m->head) free(m->head);//如果矩阵已经存在,释放原有的数据空间 m->head = (triple *) malloc ( count * sizeof (triple)); if (!m->head){ printf("Allocate memory failed!application will exit."); exit(0); } m->row = row; m->column = column; m->count = count; } /* *输入的稀疏矩阵的可能没有按照指定的排列顺序,用此来整理 *首先按行从小到大,当行等时候按列从小到大 */ void sort_matrix (matrix *m){ int i, j, count = m->count; int loc; triple * tp = m->head; triple tmp; for ( i = 0; i < count-1; i++){ loc = i; for (j = i+1; j < count; j++){ if ( tp[loc].i > tp[j].i){//按行排序 loc = j; } else if (tp[loc].i == tp[j].i && tp[loc].j > tp[j].j){ loc = j; } } memcpy (&tmp, &tp[loc], sizeof(triple)); memcpy (&tp[loc], &tp[i], sizeof(triple)); memcpy (&tp[i], &tmp, sizeof(triple)); } } /* *创建一个使用数组存储的稀疏矩阵 */ void creat_matrix (matrix *m){ int row,column,count;//存储稀疏矩阵的行、列、非零元素的个数 int i; int x,y; triple * use_triple; int value; printf ("please enter sparse matrix row,column:\n"); scanf ("%d%d", &row, &column); printf ("please enter a number as the number of non-zero elements of the sparse matrix:\n"); scanf ("%d", &count); init_matrix (m, row, column, count); use_triple = m->head; for (i = 0; i < count; i++){ repeat:printf ("please enter %d elements x and y coordinate values:", i+1); printf ("and a number as element value:"); scanf ("%d%d%d", &x, &y, &value); if ( find_item (m, x, y, i+1) ) {printf("The position has been there exists an elemetn.\n");goto repeat;} use_triple->i = x; use_triple->j = y; use_triple->value = value; use_triple ++; } sort_matrix (m); } /* *起到分割符的作用,输出count个‘—’符号 */ void print_split (int count){ int i; for (i = 0; i < count; i++) printf("-"); printf("\n"); } /* *数据稀疏矩阵中的内容 */ void print_matrix (matrix m){ int len = m.count; int i; printf("\n"); triple * sm = m.head; LINE; for (i = 0; i < len; i++){ printf("%4d | %4d | %d\n", sm->i, sm->j, sm->value); sm++; LINE; } } /* *description: 对稀疏矩阵逆转了,想将矩阵逆转,然后进行排序。 *paramtere: * sm:源稀疏矩阵 * dm:目的稀疏矩阵 */ void transpose_matrix1 (matrix *sm, matrix *dm){ int i, j, count = sm->count; triple *dt, *st = sm->head; init_matrix (dm, sm->row, sm->column, sm->count);//对目的稀疏矩阵进行初始化。 dt = dm->head ;for (i = 0; i < count; i++){ dt->i = st->j; dt->j = st->i; dt->value = st->value; sm++; dt++; } sort_matrix (dm); } /* *description: 对稀疏矩阵逆转了, *paramtere: * sm:源稀疏矩阵 * dm:目的稀疏矩阵 */ void transpose_matrix (matrix *sm, matrix *dm){ int i, j; triple *dt, *st; init_matrix (dm, sm->row, sm->column, sm->count);//对目的稀疏矩阵进行初始化。 dt = dm->head; for (i = 0; i < sm->column; i++){ st = sm->head; for (j = 0; j < sm->count; j++){ if ( st->j == i){ dt->i = i; dt->j = st->i; dt->value = st->value; dt++; } st++; } } } /* *description:向稀疏矩阵中插入一个元素,将元素个数加一 *parameter: * i,j,value:要插入元素位置的行、列、值 */ void insert_matrix (matrix *m, int i, int j, int value){ m->count++; if(1 == m->count) m->head = (triple *) malloc (sizeof(triple)); else m->head = (triple *) realloc (m->head, m->count * sizeof(triple)); (m->head)[m->count-1].i = i; (m->head)[m->count-1].j = j; (m->head)[m->count-1].value = value; } /* *description:矩阵的乘法 *pararmeter: * m1,m2:乘数和被乘数 * result:成绩结果 */ void multi_matrix (matrix *m1, matrix *m2, matrix *result){ int tmp ; //保存临时计算的结果 int i, j; //i表示计算到m2矩阵的第几列了。 int use = 0; //表示m1正在计算当前行的第几个非零位置 triple *tp = m1->head;//m1中非零元素的首地址 triple *tp2 = m2->head;//m2中非零元素的首地址 init_matrix (result, 0, 0, 0);//初始化矩阵 if (m1->column != m2->row) return ;//无法做运算的,不满组运算条件 if ( m1->column > m1->count || m2->row > m2->count){ //有矩阵的成绩关系可以知,m1中的一行与m2中的一列做运算。 //如果m1中的非零个数不满足一行,m2中的非零个数不满足一列。没有做运算的必要 return ; } /* *1.首先找本行中的一个m1中非零元素tp[usue], *2.查找m2[tp[use].j][i]元素是否存,存在转到第3步,否则转到第4步 *3.计算两者的成绩加入到到tmp中。 *4.查找同行的下一个非零元素。如存在转到第2不,不存在转到第5步 *5.清空临时数据,进入下一个行,转到第1步。 */ while ( tp < &tp[m1->count] ){//判断m1中是否还有未计算的元素,没有的话,计算结束 for (i = 0; i < m2->column; i++){//用来控制与m2中的第几列做运算 use = 0;//计算本行中的第一个非零元素 tmp = 0;//计算的结果 for (j = 0; j < m2->count; j++){//遍历m2中的所有元素,差找目标元素 if(tp2[j].j == i && tp2[j].i == tp[use].j ){ tmp += tp2[j].value * tp[use].value; if( tp[use].j == m1->column){ break; } if (tp >= &((m1->head)[m1->count]) || tp[use].i != tp[use+1].i ) break; use ++; } } if (tmp > 0) insert_matrix (result ,i ,j ,tmp); } //转到下一行 while ( tp->i == tp[1].i){ tp++; if ( tp >= &((m1->head)[m1->count]) ) return ; } tp++; } } void destroy_matrix (matrix *m){ m->row = 0; m->column = 0; m->count = 0; free (m->head);
}