稀疏矩阵的压缩存储

本文介绍了一种使用三元组顺序表表示稀疏矩阵的方法,并提供了矩阵逆置、相加、相减和相乘等基本运算的C语言实现。通过行逻辑链接信息优化了存储结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验目的:

深入研究数组的存储表示和实现技术,着重掌握对稀疏矩阵的表示方法及其运算的实现。

问题描述:

稀疏矩阵是指那些多数元素为零的矩阵。利用‘稀疏’特点进行存储和计算可以大大节省存储 空间,提高效率。通过对稀疏矩阵的存储表示,实现矩阵的基本操作。

实验要求:

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; 
}

转置函数还有一点问题,没有修改行链接,下次再解决。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值