实验目的:
深入研究数组的存储表示和实现技术,着重掌握对稀疏矩阵的表示方法及其运算的实现。
问题描述:
稀疏矩阵是指那些多数元素为零的矩阵。利用‘稀疏’特点进行存储和计算可以大大节省存储 空间,提高效率。通过对稀疏矩阵的存储表示,实现矩阵的基本操作。
实验要求:
1.要求矩阵的输入形式采用三元组表示,以“带行逻辑链接信息”的三元组顺序表表示稀疏矩阵。
2.设计矩阵的逆置算法,实现矩阵的逆置。
3.实现两个稀疏矩阵的相加、相减和相乘等运算。
4.要求运算结果的矩阵则以通常的阵列形式出现。
C语言实现代码:
#include<stdio.h>
#define OVERFLOW 1
#define OK 1
#define ERROR 0
typedef int Status;
typedef int Elemtype;
#define MAXRC 100
//------------------稀疏矩阵的三元组顺序表存储表示-----------------
#define MAXSIZE 12500//假设非零元个数的最大值为12500
typedef struct{
int i,j;
Elemtype e;
}Triple;
/*-------行逻辑链接的顺序表---------*/
typedef struct{
Triple data[MAXSIZE+1];//非零元三元组表
int rpos[MAXRC+1]; //各行第一个非零元的位置表
int mu,nu,tu;//矩阵的行数、列数、和非零元个数
}RLSMatrix;
/*---------------基本操作---------*/
Status CreatSMatrix(RLSMatrix &M);//创建稀疏矩阵
Status DestorySMatrix(RLSMatrix &M);//销毁稀疏矩阵
Status PrintSMatrix(RLSMatrix &M);//打印稀疏矩阵
//CopySMatrix(RLSMatrix M,RLSMatrix &T);//稀疏矩阵的复制
Status AddSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q);//稀疏矩阵的相加
//SubtSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q);//稀疏矩阵的相减
Status MultSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q);//稀疏矩阵的相乘
Status TransposeSMatrix(RLSMatrix M,RLSMatrix &T);//稀疏矩阵的转置
Status FastTransposeSMatrix(RLSMatrix M,RLSMatrix &T);//快速转置
//ADT SpareseMatrix
Status CreatSMatrix(RLSMatrix &M)
{
printf("请输入要创建的矩阵的行数、列数、和非零元个数\n");
scanf("%d%d%d",&M.mu,&M.nu,&M.tu);
printf("请输入矩阵的行、列、元素:\n");
for(int c=1;c<=M.tu;++c)
{
scanf("%d",&M.data[c].i);
scanf("%d",&M.data[c].j);
scanf("%d",&M.data[c].e);
}
for(int c=1;c<=M.mu;++c){
printf("请输入第%d行的第一个非零元素位置:",c);
scanf("%d",&M.rpos[c]);
}
return OK;
}//CreatSMatrix
bool Value(RLSMatrix &t,Elemtype x,int p,int q) //三元组元素赋值
{
int k=1,k1;
if (p>t.mu || q>t.nu)
return false; //失败时返回false
while (k<t.tu && p>t.data[k].i) k++; //查找行
while (k<t.tu && p==t.data[k].i && q>t.data[k].j) k++;//查找列
if (t.data[k].i==p && t.data[k].j==q) //存在这样的元素
t.data[k].e=x;
else //不存在这样的元素时插入一个元素
{
for (k1=t.tu; k1>=k; k1--)
{
t.data[k1+1].i=t.data[k1].i;
t.data[k1+1].j=t.data[k1].j;
t.data[k1+1].e=t.data[k1].e;
}
t.data[k].i=p;
t.data[k].j=q;
t.data[k].e=x;
t.tu++;
}
return true; //成功时返回true
}//Value
bool Assign(RLSMatrix t,Elemtype &x,int p,int q) //将指定位置的元素值赋给变量
{
int k=1;
if (p>t.mu || q>t.nu)
return false; //失败时返回false
while (k<t.tu && p>t.data[k].i) k++; //查找行
while (k<t.tu && p==t.data[k].i && q>t.data[k].j) k++;//查找列
if (t.data[k].i==p && t.data[k].j==q)
x=t.data[k].e;
else
x=0; //在三元组中没有找到表示是零元素
return true; //成功时返回true
}//Assign
Status TransposeSMatrix(RLSMatrix M,RLSMatrix &T)
{
T.mu=M.mu; T.nu=M.nu; T.tu=M.tu;
if(T.tu){
int q=1;
for(int col=1;col<=M.nu;++col){
for(int p=1;p<=M.tu;++p){
if(M.data[p].j==col){
T.data[q].i=M.data[p].j; T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e; ++q;
}
}
}
}//if
return OK;
}//TransposeSMatrix
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q) {
// 求矩阵乘积Q=M*N,采用行逻辑链接存储表示。
int arow,brow,p,q,t,ctemp[30],l,ccol,tp;
if (M.nu != N.mu) return ERROR;
Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; // Q初始化
if (M.tu*N.tu != 0) { // Q是非零矩阵
for (arow=1; arow<=M.mu; ++arow) { // 处理M的每一行
for (l=1; l<=M.nu; ++l) ctemp[l] = 0; // 当前行各元素累加器清零
Q.rpos[arow] = Q.tu+1;
if (arow<M.mu) tp=M.rpos[arow+1];
else tp=M.tu+1;
for (p=M.rpos[arow]; p<tp;++p) { // 对当前行中每一个非零元
brow=M.data[p].j; // 找到对应元在N中的行号
if (brow < N.mu ) t = N.rpos[brow+1];
else t = N.tu+1;
for (q=N.rpos[brow]; q< t; ++q) {
ccol = N.data[q].j; // 乘积元素在Q中列号
ctemp[ccol] += M.data[p].e * N.data[q].e;
} // for q
} // 求得Q中第crow( =arow)行的非零元
for (ccol=1; ccol<=Q.nu; ++ccol) // 压缩存储该行非零元
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];
} // if
} // for arow
} // if
return OK;
} // MultSMatrix
Status AddSMatrix(RLSMatrix M,RLSMatrix N,RLSMatrix &Q){
if(M.mu!=N.mu||M.nu!=N.nu) return ERROR;
Elemtype v1,v2,v3;
Q.mu=M.mu; Q.nu=M.nu; Q.tu=0;
int i,j;
for(i=1;i<=M.mu;i++){
for(j=1;j<=M.nu;j++){
Assign(M,v1,i,j);
Assign(N,v2,i,j);
v3=v1+v2;
if(v3)
Value(Q,v3,i,j);
}
}
return OK;
}//AddSMatrix
Status FastTransposeSMatrix(RLSMatrix M,RLSMatrix &T){
T.mu=M.mu; T.nu=M.mu; T.tu=M.tu;
int col,p,q,t,cpot[100],num[100];
if(T.tu){
for(col=1;col<=M.nu;++col)
num[col]=0;
for(t=1;t<=M.tu;++t) ++num[M.data[t].j];//求M中的每一列含非零元个数
cpot[1]=1;
//求第col列中第一个非零元在b.data中的序号
for(col=2;col<=M.nu;++col) cpot[col]=cpot[col-1]+num[col-1];
for(p=1;p<=M.tu;++p){
col=M.data[p].j; q=cpot[col];
T.data[q].i=M.data[p].j; T.data[q].j=M.data[p].i;
T.data[q].e=M.data[p].e; ++cpot[col];
}//for
}//if
return OK;
}//FastTransposeSMatrix
Status DestorySMatrix(RLSMatrix &M){
M.mu=0; M.nu=0; M.tu=0;
return OK;
}//DestorySMatrix
Status PrintSMatrix(RLSMatrix &M){
for(int c=1;c<=M.tu;c++)
{
printf("(%d,%d,%d)",M.data[c].i,M.data[c].j,M.data[c].e);
}
printf("\n");
return OK;
}//PrintSMatrix
int main()
{
RLSMatrix M,T,N,Q;//T为M逆置后的矩阵
int temp=1;//用于菜单的判断
while(temp)
{
printf("----菜单---\n");
printf("1.逆置\t2.相乘\t3.相加\t4.销毁\t5.快速逆置");
int i;
scanf("%d",&i);
switch(i)
{
case 1:printf("建立稀疏矩阵M\t");
CreatSMatrix(M); printf("M:");
PrintSMatrix(M);
TransposeSMatrix(M,T); printf("T:");
PrintSMatrix(T);
break;
case 2:printf("建立稀疏矩阵M\t");
CreatSMatrix(M); printf("M:");
PrintSMatrix(M);
printf("建立稀疏矩阵N\t");
CreatSMatrix(N); printf("N:");
PrintSMatrix(N);
MultSMatrix(M,N,Q); printf("Q:");
PrintSMatrix(Q);
break;
case 3:printf("建立稀疏矩阵M\t");
CreatSMatrix(M); printf("M:");
PrintSMatrix(M);
printf("建立稀疏矩阵N\t");
CreatSMatrix(N); printf("N:");
PrintSMatrix(N);
AddSMatrix(M,N,Q); printf("Q:");
PrintSMatrix(Q);
break;
case 4:DestorySMatrix(M);
break;
case 5:printf("建立稀疏矩阵M\t");
CreatSMatrix(M); printf("M:");
PrintSMatrix(M);
FastTransposeSMatrix(M,T); printf("T:");
PrintSMatrix(T);
break;
}//switch
}//while
return 0;
}
转置函数还有一点问题,没有修改行链接,下次再解决。