三元组表示的稀疏矩阵的加法和乘法

#include <stdio.h>
#include <stdlib.h>
//函数结果状态码
#define OK        1
#define ERROR     0
#define OVERFLOW -1 
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
// ----- 稀疏矩阵的三元组顺序表存储表示 -----
#define MAXSIZE 100                      //假设非零元个数的最大值为100
#define MAXRC   100
typedef struct {
        int i,j;                           //非零元的行下标和列下标
        int e;                             //非零元的值
}Triple;
typedef struct {
        Triple data[MAXSIZE + 1];          //非零元三元组表,data[0]未用
        int    rpos[MAXRC + 1];            //各行的第一个非零元的位置表 
        int    mu, nu, tu;                 //矩阵的行数、列数和非零元个数 
}RLSMatrix;

Status CreateSMatrix(RLSMatrix *M);                            //创建稀疏矩阵M,采用三元组存储
Status PrintSMatrix(RLSMatrix M);                              //输出稀疏矩阵M
Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q);     //求稀疏矩阵的和Q = M + N
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q);    //求稀疏矩阵乘积Q = M ×N 

main()
{
    RLSMatrix A, B, C;//稀疏矩阵A、B和C均以三元组表作为存储结构,C存放A、B相加相乘的结果 
    //创建稀疏矩阵A、B
    printf("请输入稀疏矩阵A\n"); 
    CreateSMatrix(&A);
    printf("稀疏矩阵A为:\n");
    PrintSMatrix(A);
    printf("\n\n");
    printf("请输入稀疏矩阵B\n");
    CreateSMatrix(&B);
    printf("稀疏矩阵B为:\n");
    PrintSMatrix(B);
    printf("\n\n");
    //求稀疏矩阵的和C = A + B,并输出相加结果矩阵C 
    if(AddSMatrix(A, B, &C))
    {
         printf("求疏矩阵的和C = A + B,并输出相加结果矩阵C:\n");
         PrintSMatrix(C);
         printf("\n");
    }
    else printf("两个矩阵行列数不完全相等,不是同类矩阵,不能相加。\n" );
    
    //求稀疏矩阵乘积C = A ×B,并输出相乘结果矩阵C
    if(MultSMatrix(A, B, &C))
    {
         printf("稀疏矩阵乘积C = A ×B,并输出相乘结果矩阵C:\n");
         PrintSMatrix(C);
         printf("\n");
    }
    else printf("稀疏矩阵A的列数和B的行数不相等,不能相乘。\n");
    printf("\n");
    //程序结束
    system("pause");
    return 0; 
}
//创建稀疏矩阵M,采用三元组表存储表示
Status CreateSMatrix(RLSMatrix *M)
{
       int m, n, t, e;                //行数m,列数n,非零元个数t和非零元值e 
       int i, j, k, a, b;                   //中间变量
       int num[MAXSIZE];              //每行非零元素个数
       int flag [MAXSIZE][MAXSIZE];   //标记数组:此位置是否已经有非零元素 
       
       for(i = 0; i < MAXSIZE; i++)   //标记数组的初始化 
            for(j = 0; j < MAXSIZE; j++)
                 flag [i][j] = 0;
                  
       //输入M的行数、列数和非零元个数
       do {
          printf("请分别输入矩阵的行数、列数和非零元个数:\n"); 
          printf("行数:");
          scanf("%d", &m);
          printf("列数:");
          scanf("%d", &n);
          printf("非零元的个数:");
          scanf("%d", &t);
          if(m < 0 || n < 0 || t < 0 || t > m * n) printf("输入的数据不符合要求!!!");
       } while(m < 0 || n < 0 || t < 0 || t > m * n);
       M->mu = m, M->nu = n, M->tu = t;//保存 
       //按行序输入非零元
       if(t == 0) return OK;
       for(k = 1; k <= t; k++)
       {
            do {
               printf("请输入第%d个非零元(总共%d个)的行和列:\n", k, t);
               printf("对应行:");
               scanf("%d", &i);
               printf("对应列:");
               scanf("%d", &j);              
               if(i <= 0 || i > m || j <= 0 || j > n) 
                    printf("输入行或列不符合要求!!!\n");
               if(flag [i][j] != 0) {
                    printf("此处已存在非零元素!!!\n");
                    flag [i][j] = 2;
               }
               else
                    flag [i][j] = 1;      
            } while(i <= 0 || i > m || j <= 0 || j > n || flag [i][j] == 2);//检测输入是否合法 
 
            do {
               printf("非零元:");
               scanf("%d", &e);
               if(e == 0) printf("输入为0,请重新输入!!!\n");
            } while(e == 0); //检测输入是否合法 
            //按行序保存数据 
            for(a = 1; a <= k-1 && (i > M->data[a].i || (i == M->data[a].i && j > M->data[a].j)); a++);//找到此三元组插入的位置 
            for(b = k-1; b >= a; b--)
                 M->data[b+1] = M->data[b];//行序比它大的三元组依次向后移动 
            M->data[a].i = i, M->data[a].j = j, M->data[a].e = e;//保存数据
       }
       //求rpos
       if(M->tu)
       {
            for(i = 1; i <= M->mu; i++) num[i] = 0;//初始化 
            for(t = 1; t <= M->tu; t++) ++num[M->data[t].i];//求M中每一行含非零元素个数
            //求rpos
            M->rpos[1] = 1;
            for(i = 2; i <= M->mu; i++) M->rpos[i] = M->rpos[i-1] + num[i-1]; 
       }  
       return OK;          
}
//输出稀疏矩阵M
Status PrintSMatrix(RLSMatrix M)
{
       int i, j, k;//中间变量
       //输出
       for(i = 1, k = 0; i <= M.mu; i++)
       {
            for(j = 1; j <= M.nu; j++)
            {
                 if(M.data[k+1].i == i && M.data[k+1].j == j) 
                 {
                      printf("%d\t", M.data[k+1].e);
                      k++;
                 }
                 else printf("0\t");
            }
            printf("\n");
       }
       printf("矩阵共有%d行%d列共%d个非零元素", M.mu, M.nu, M.tu);
       return OK;
}
//求稀疏矩阵的和Q = M + N
Status AddSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{
       int i = 1, j = 1, k = 1;              //中间变量   
       //检查稀疏矩阵M和N的行数和列数是否对应相等 
       if(M.mu != N.mu || M.nu != N.nu) 
       {//不完全相等,退出 
            return ERROR;   
       }
       if(M.tu * N.tu == 0) return OK;//Q为零矩阵,直接返回 
       //初始化矩阵Q
       Q->mu = M.mu, Q->nu = M.nu, Q->tu = 0;
       //执行矩阵相加,按行的顺序相加,分为四种情况 
       while(i <= M.tu && j <= N.tu)//M和N均不为空 
       {
            if((M.data[i].i == N.data[j].i && M.data[i].j < N.data[j].j) || (M.data[i].i < N.data[j].i))//矩阵M当前元素在矩阵N当前元素的前面 
            {
                 Q->tu++;//非零元素增加
                 Q->data[k].i = M.data[i].i, Q->data[k].j = M.data[i].j, Q->data[k].e = M.data[i].e;//赋值
                 i++, k++;//移动指针 
            }
            else if((M.data[i].i == N.data[j].i && M.data[i].j > N.data[j].j) || (M.data[i].i > N.data[j].i))//矩阵M当前元素的在矩阵N当前元素的后面 
            {
                 Q->tu++;//非零元素增加
                 Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = N.data[j].e;//赋值
                 j++, k++;//移动指针 
            }
            else if(M.data[i].e + N.data[j].e)//M和N当前结点对应且两元素之和不为零
            {
                 Q->tu++;//非零元素增加
                 Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = M.data[i].e + N.data[j].e;//赋值
                 i++, j++, k++;//移动指针 
            } 
            else //M和N当前结点对应且两元素之和为零
            {
                 i++, j++;//指针向右移
            }
       }
       //将矩阵M的剩余元素插入矩阵Q    
       while(i <= M.tu)
       {
            Q->tu++;//非零元素增加
            Q->data[k].i = M.data[i].i, Q->data[k].j = M.data[i].j, Q->data[k].e = M.data[i].e;//赋值
            i++, k++;//移动指针 
       } 
       //将矩阵N的剩余元素插入矩阵Q 
       while(j <= N.tu)
       {
            Q->tu++;//非零元素增加
            Q->data[k].i = N.data[j].i, Q->data[k].j = N.data[j].j, Q->data[k].e = N.data[j].e;//赋值
            j++, k++;//移动指针 
       } 
       return OK;
}
//求稀疏矩阵乘积Q = M ×N 
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix *Q)
{
       int arow, brow, ccol, i, t, ctemp[N.nu+1], p, q, tp;//中间变量 
       //检查稀疏矩阵M的列数和N的行数是否对应相等 
       if(M.nu != N.mu) return ERROR;//稀疏矩阵M的列数和N的行数不相等,不能相乘,退出 
       //初始化矩阵Q
       Q->mu = M.mu, Q->nu = N.nu, Q->tu = 0;
       //相乘
       if(M.tu * N.tu != 0)//Q是非零矩阵
       {
            for(arow = 1; arow <= M.mu; ++arow)//处理M的每一行 
            {
                 for(i = 0; i <= N.nu; ++i) ctemp[i] = 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; 
                      } 
                 }//求得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];          
                      }    
                 } 
            }   
       } 
       return OK;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值