http://blog.youkuaiyun.com/snakewarhead/article/details/6256304
此操作的算法我就不多说了,代码里面叙述得很清楚了。下面就是此程序:
[cpp]
view plain
copy
- # include <stdio.h>
- # include <stdlib.h>
- # define NULL 0
- # define OK 1
- # define ERROR 0
- # define MAXSIZE 100 /* 矩阵中非零元的最大值 */
- # define MAXRC 10 /* 矩阵的最大行值 */
- typedef int status ;
- /********** 稀疏矩阵的行逻辑链接的顺序表存储表示 **********/
- typedef struct /* 非零元的三元组 */
- {
- int i, j ; /* 非零元的行下标和列下标 */
- int e ;
- }Triple;
- typedef struct /* 稀疏矩阵的行逻辑链接的顺序表 */
- {
- Triple data[MAXSIZE+1]; /* 非零三元组表,data[0]未用,以下定义的数组都是从1开始 */
- int rpos[MAXRC+1]; /* 代表各行第一个非零元的序号表,其值为data的下标 */
- int mu,nu,tu; /* 矩阵的行数、列数、非零元的个数 */
- }RLSMatrix; /* R:row L:logic S:sequence */
- /********* 基本操作的函数原型的声明 *********/
- status CreateSMatrix_RL(RLSMatrix * matrix);
- // 创建一个稀疏矩阵;
- // 输入行数、列数,支持乱序输入三元组,并计数;
- // 以行为主序进行重新排列,并记录每行起始位置于matrix->rpos[row];
- // 若非零元超过 MAXSIZE或行数超过MAXRC,则返回ERROR,否则OK;
- void PrintSMatrix_RL(RLSMatrix * matrix);
- // 输入矩阵,打印出矩阵的行数、列数、非零元个数,以及整个矩阵;
- status MultSMatrix_RL(RLSMatrix * M,RLSMatrix * N,RLSMatrix * Q);
- // 输入两个稀疏矩阵M和N,并初始化Q,然后计算M*N的值赋给Q;
- // 如果M->mu!=N->nu或列数大于MAXRC或者计算出的非零元个数大于MAXSIZE,都返回ERROR,否则OK;
- // 计算过程如下:
- // 1. 由于矩阵M和Q的行数相等并且<a href="http://lib.youkuaiyun.com/base/c" class='replace_word' title="C语言知识库" target='_blank' style='color:#df3434; font-weight:bold;'>C语言</a>以行为主序进行存储,所以以M进行逐行的扫描。
- // 2. 使Q的此行逻辑表的序号等于其非零元个数Q.tu+1,以表示其行的首个元素的序号。
- // 3. 从行中找到M的非零元,并以它的列值为N的行号,对N进行行的扫描,若存在,则依次计算它们,并把其值累加到一个以N中这个对应非零元的列值为序号的临时数组ctemp[ccol]中。
- // 4. 在M的当前行完成扫描后,将ctemp[ccol]不为0的值,压入到Q矩阵的三元组,累加++Q.tu,若Q.tu大于了MAXSIZE,这返回ERROR。
- /************ main( ) 函数对矩阵乘法的实现 ************/
- void main()
- {
- RLSMatrix * M,* N,* Q;
- if(!(M=(RLSMatrix *)malloc(sizeof(RLSMatrix))))
- exit(ERROR);
- if(!(N=(RLSMatrix *)malloc(sizeof(RLSMatrix))))
- exit(ERROR);
- if(!(Q=(RLSMatrix *)malloc(sizeof(RLSMatrix))))
- exit(ERROR);
- if(CreateSMatrix_RL(M)&&CreateSMatrix_RL(N))
- {
- printf("/nput out M:/n");
- PrintSMatrix_RL(M); /* 打印出M */
- printf("/nput out N:/n");
- PrintSMatrix_RL(N); /* 打印出N */
- if(MultSMatrix_RL(M,N,Q))
- {
- printf("/n/n/n M * N :/n");
- PrintSMatrix_RL(Q); /* 计算结果 */
- }
- else
- printf("M.mu and N.nu are not mathing/n");
- }
- else
- printf("input error./n");
- }
- /*********** 基本操作的算法描述 ****************/
- status CreateSMatrix_RL(RLSMatrix * matrix)
- // 创建一个稀疏矩阵;
- // 输入行数、列数,支持乱序输入三元组,并计数;
- {
- int num=0,p,q,min,temp; // 中间变量;
- int row;
- printf("input the total row and col:/n");
- scanf("%d%d",&matrix->mu,&matrix->nu); // 输入行数、列数;
- if(matrix->mu>MAXRC)
- return ERROR;
- printf("row col val/n");
- scanf("%d%d%d",&matrix->data[num+1].i,&matrix->data[num+1].j,&matrix->data[num+1].e);
- while(matrix->data[num+1].i) // 乱序输入三元组;
- {
- if(++num>MAXSIZE)
- return ERROR;
- scanf("%d%d%d",&matrix->data[num+1].i,&matrix->data[num+1].j,&matrix->data[num+1].e);
- }
- matrix->tu=num; // num的值即为此矩阵的非零元个数;
- for(p=1;p<=matrix->tu-1;++p) // 按行为主序依次重新排列非零元
- {
- min=p; // 使较小的行数、列数的元的序号min为当前值p;
- for(q=p+1;q<=matrix->tu;++q) // 开始依次比较;
- {
- if(matrix->data[min].i>matrix->data[q].i||(matrix->data[min].i==matrix->data[q].i&&matrix->data[min].j>matrix->data[q].j))
- min=q; // 在乱序的三元表中,始终保证min是较小的行列数的序号;
- }
- temp=matrix->data[min].i; // 交换行值;
- matrix->data[min].i=matrix->data[p].i;
- matrix->data[p].i=temp;
- temp=matrix->data[min].j; // 交换列值;
- matrix->data[min].j=matrix->data[p].j;
- matrix->data[p].j=temp;
- temp=matrix->data[min].e; // 交换元素值;
- matrix->data[min].e=matrix->data[p].e;
- matrix->data[p].e=temp;
- }
- for(row=1,num=0;row<=matrix->mu;++row) // 记录matrix->rpos[row];
- {
- matrix->rpos[row]=num+1;
- while(matrix->data[num+1].i==row)
- ++num;
- }
- return OK;
- }
- // 时间复杂度分析:
- // 1. 输入非零元:O(tu); 2. 重新排列(最坏情况下);O(tu*(tu-1)) ; 3. 记录行逻辑表:O(mu)
- void PrintSMatrix_RL(RLSMatrix * matrix)
- // 输入矩阵,打印出矩阵的行数、列数、非零元个数,以及整个矩阵;
- {
- int row,col;
- int num=0;
- printf("/nrow:%d col:%d number:%d/n",matrix->mu,matrix->nu,matrix->tu);
- for(row=1;row<=matrix->mu;++row)
- {
- for(col=1;col<=matrix->nu;++col)
- {
- if(num+1<=matrix->tu&&matrix->data[num+1].i==row&&matrix->data[num+1].j==col)
- {
- ++num;
- printf("%4d",matrix->data[num].e); /* 当扫描到非零元的行列值与之相等时,输出其值 */
- }
- else
- printf("%4d",NULL); /* 没有非零元的地方补0 */
- }
- printf("/n"); /* 每行输入完毕后,换行 */
- }
- }
- // 时间复杂度:O(mu*nu).
- status MultSMatrix_RL(RLSMatrix * M,RLSMatrix * N,RLSMatrix * Q)
- // 输入两个稀疏矩阵M和N,并初始化Q,然后计算M*N的值赋给Q
- {
- int arow,brow,ccol;
- int * ctemp; /* 以N的列值为序号的临时数组 */
- int tp,p,tq,q; /* 中间变量 */
- if(M->nu!=N->mu)
- return ERROR;
- Q->mu=M->mu; /* 初始化Q */
- Q->nu=N->nu;
- Q->tu=0;
- if(!(ctemp=(int *)malloc((N->nu+1)*sizeof(int)))) /* 动态建立累加器 */
- exit(ERROR);
- if(M->tu*N->tu!=0) /* Q是非零矩阵 */
- {
- for(arow=1;arow<=M->mu;++arow) /* 逐行扫描 */
- {
- for(ccol=1;ccol<=N->nu;++ccol)
- ctemp[ccol]=0; /* 初始化累加器 */
- Q->rpos[arow]=Q->tu+1;
- if(arow<M->mu)
- tp=M->rpos[arow+1]; /* tp是M下一行的序号 */
- else
- tp=M->tu+1;
- for(p=M->rpos[arow];p<tp;++p) /* 从M的当前行找到元素 */
- {
- brow=M->data[p].j; /* 对应元在N中的行号 */
- if(brow<N->mu)
- tq=N->rpos[brow+1]; /* tq是N下一行的行号 */
- else
- tq=N->tu+1;
- for(q=N->rpos[brow];q<tq;++q) /* 以M的对应元的列号为N的行号进行扫描 */
- {
- ccol=N->data[q].j; /* 提取对应元的列号 */
- ctemp[ccol]+=M->data[p].e*N->data[q].e;
- /* 两个对应元的值相乘并累加到以列号为序号的累加器中 */
- }
- }
- for(ccol=1;ccol<=Q->nu;++ccol) /* 将此行非零元压缩入Q中 */
- {
- if(ctemp[ccol])
- {
- if(++Q->tu>MAXSIZE)
- return ERROR;
- Q->data[Q->tu].i=arow;
- Q->data[Q->tu].j=ccol;
- Q->data[Q->tu].e=ctemp[ccol];
- }
- }
- }
- }
- return OK;
- }
- // 时间复杂度:O(M->mu*(N->nu+M->nu*N->nu+N->nu));
status CreateSMatrix_RL(RLSMatrix * matrix)
这个函数我用 2 种算法进行了编写:第一种不支持乱序输入,而且输入很麻烦。第二种则使得输入很方便、清楚。
所以,我想总结一下函数在声明时,对函数进行说明的流程:
1. 确定功能,详细描述这个功能,即要达到哪些效果。好的功能能够使程序更加人性化。
2. 设计算法。
3. 尽量给出此函数的完整定义。
我觉得确定功能应该是首要工作,因为它是整个思路的方向,所以我放在了第一位,必须认真地对待。