首页 > 其他分享 >[数据结构] 稀疏矩阵的加法与乘法

[数据结构] 稀疏矩阵的加法与乘法

时间:2023-02-19 18:12:25浏览次数:32  
标签:零元 int tu 矩阵 ++ 加法 数据结构 data 乘法

稀疏矩阵的加法

传统矩阵的加法

矩阵相加的前提是两个矩阵的行数和列数相等,将矩阵的每个元素对应相加即可。

void NormalAddMatrix(int A[][N], int B[][N], int C[][N]){
    for(int i = 0; i < m; i ++ )
        for(int j = 0; j < n; j ++ )
            C[i][j] = A[i][j] + B[i][j];
}

稀疏矩阵的加法

稀疏矩阵是由三元组表表示的,在进行矩阵相加的操作时,需要对当前两个非零元行列的情况进行分类:
1.当前两个非零元行相同
(1)当前 A 遍历到的非零元的列小于当前 B 遍历到的非零元的列:将 A 此时的非零元加入到 C 的三元组表中
(2)当前 A 遍历到的非零元的列大于当前 B 遍历到的非零元的列:将 B 此时的非零元加入到 C 的三元组表中
(3)当前 A 遍历到的非零元的列等于当前 B 遍历到的非零元的列:将 A 此时的非零元和 B 此时非零元相加后加入到 C 的三元组表中

2.当前两个非零元行不相同
(1)A 中的非零元已经遍历完了 或者 A 此时的非零元的行大于 B 的非零元的行:将 B 此时的非零元加入到 C 的三元组表中
(2)B 中的非零元已经遍历完了 或者 A 此时的非零元的行小于 B 的非零元的行:将 A 此时的非零元加入到 C 的三元组表中

//稀疏矩阵三元组加法
void AddSMatrix(TSMatrix a, TSMatrix b, TSMatrix &c){
    int i = 0, j = 0, k = 0;
    ElemType v;                            //用于计算和
    if(a.mu != b.mu || a.nu != b.nu){       //两矩阵无法相加
        printf("两矩阵无法相加。\n");
        return;  
    }

    c.mu = a.mu;
    c.nu = a.nu;
    while(i < a.tu || j < b.tu){
      //若行相等,看列
      if(a.data[i + 1].i == b.data[j + 1].i){
        //行相同时的第一种情况
        if(a.data[i + 1].j < b.data[j + 1].j){
            c.data[k + 1].i = a.data[i + 1].i;
            c.data[k + 1].j = a.data[i + 1].j;
            c.data[k + 1].e = a.data[i + 1].e;
            k++;   
            i++;        //前往下一个a中的非0元
        }
        //行相同时的第二种情况
        else if(a.data[i + 1].j > b.data[j + 1].j){
            c.data[k + 1].i = b.data[j + 1].i;
            c.data[k + 1].j = b.data[j + 1].j;
            c.data[k + 1].e = b.data[j + 1].e;
            k++;
            j++;        //前往下一个b中的非0元
        }
        //行相同的第三种情况
        else{
            v = a.data[i + 1].e + b.data[j + 1].e;
            if(v != 0){
                c.data[k + 1].i = a.data[i + 1].i;
                c.data[k + 1].j = a.data[i + 1].j;
                c.data[k + 1].e = v;
                k++;
            }
            i++;
            j++;
        }
      }
      //若行不相同 的两种情况
      else if(i == a.tu || a.data[i + 1].i > b.data[j + 1].i && j != b.tu){
          c.data[k + 1].i = b.data[j + 1].i;
          c.data[k + 1].j = b.data[j + 1].j;
          c.data[k + 1].e = b.data[j + 1].e;
          k++;
          j++;      //前往下一个b的非0元
      }
      else if(j == b.tu || a.data[i + 1].i < b.data[j + 1].i && i != a.tu){   
          c.data[k + 1].i = a.data[i + 1].i;
          c.data[k + 1].j = a.data[i + 1].j;
          c.data[k + 1].e = a.data[i + 1].e;
          k++;
          i++;      //前往下一个a的非0元
      }
    }
    c.tu = k;
}


稀疏矩阵的乘法

传统矩阵的乘法

矩阵相乘的前提是矩阵 A 的列数等于矩阵 B 的行数,假设矩阵 A 是一个 m * l 的矩阵, B 是一个 l * n 的矩阵,两者相乘后得到一个 m * n 的新矩阵 *C

void NormalMultMatrix(int A[][N], int B[][N], int C[][N]){
    for(int i = 0; i < m; i ++ )
        for(int j = 0; j < n; j ++ )
            for(int k = 0; k < l; k ++ )
                C[i][j] += A[i][k] * B[k][j];
}

稀疏矩阵的乘法

乘法辅助函数

我们可以仿照传统矩阵乘法的样式来实现三元组表示矩阵的相乘,对于相乘后得到的矩阵 C ,每个元素即 C[i][j] ,其实只需要在 AB 中找到对应下标相同的 A[i][k]B[k][j] 即可。

//乘法辅助函数 找到对应下标相同的元素 A[i][k] 和 B[k][j]
int Getval(TSMatrix a, int i, int j){
    int k = 1;     //矩阵三元组下标
    while(k <= a.tu && (a.data[k].i != i || a.data[k].j != j))
        k++;
    if(k <= a.tu)
        return a.data[k].e;
    else
        return 0;
}

稀疏矩阵的乘法代码

有了这个辅助函数,就可以轻松实现三元组表示的矩阵的乘法了。

//稀疏矩阵三元组乘法
void MultSMatrix(TSMatrix a, TSMatrix b, TSMatrix &c){
    int p = 0;
    ElemType s;
    if(a.nu != b.mu){
       printf("两矩阵无法相乘\n");
       return;
    }

    for(int i = 1; i <= a.mu; i++){
        for(int j = 1; j <= b.nu; j++){
            s = 0;
            for(int k = 1; k <= a.nu; k++)
               s += Getval(a, i, k) * Getval(b, k, j);
            if(s != 0){
               c.data[p + 1].i = i;
               c.data[p + 1].j = j;
               c.data[p + 1].e = s;
               p++;
            }
        }
    }
    c.mu = a.mu;
    c.nu = b.nu;
    c.tu = p;
}


程序测试

完整程序代码

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10000

typedef int ElemType;
typedef struct{

    int i, j;
    ElemType e;

}Triple;

typedef struct{

    Triple data[MAXSIZE];
    int mu, nu, tu;          //矩阵行数,列数和非0元个数

}TSMatrix;


//输入稀疏矩阵数据
void InPutM(TSMatrix &M){
    printf("输入稀疏矩阵的 行数, 列数, 非0元个数 :\n");
    scanf("%d %d %d", &M.mu, &M.nu, &M.tu);
    printf("输入矩阵非0元素的 所在行i, 所在列j, 值e:\n");
    for(int k = 1; k <= M.tu; k++){
        scanf("%d %d %d", &M.data[k].i, &M.data[k].j, &M.data[k].e);
    }
}


//打印稀疏矩阵三元组数据
void PrintM(TSMatrix T){
    printf("  %d    %d    %d\n", T.mu, T.nu, T.tu);
    printf("  ------------\n");
    for(int k = 1; k <= T.tu; k++){
        printf("  %d    %d    %d\n",T.data[k].i, T.data[k].j, T.data[k].e);
    }
}


//稀疏矩阵三元组加法
void AddSMatrix(TSMatrix a, TSMatrix b, TSMatrix &c){
    int i = 0, j = 0, k = 0;
    ElemType v;                            //用于计算和
    if(a.mu != b.mu || a.nu != b.nu){       //两矩阵无法相加
        printf("两矩阵无法相加。\n");
        return;  
    }

    c.mu = a.mu;
    c.nu = a.nu;
    while(i < a.tu || j < b.tu){
      //若行相等,看列
      if(a.data[i + 1].i == b.data[j + 1].i){
        //行相同时的第一种情况
        if(a.data[i + 1].j < b.data[j + 1].j){
            c.data[k + 1].i = a.data[i + 1].i;
            c.data[k + 1].j = a.data[i + 1].j;
            c.data[k + 1].e = a.data[i + 1].e;
            k++;   
            i++;        //前往下一个a中的非0元
        }
        //行相同时的第二种情况
        else if(a.data[i + 1].j > b.data[j + 1].j){
            c.data[k + 1].i = b.data[j + 1].i;
            c.data[k + 1].j = b.data[j + 1].j;
            c.data[k + 1].e = b.data[j + 1].e;
            k++;
            j++;        //前往下一个b中的非0元
        }
        //行相同的第三种情况
        else{
            v = a.data[i + 1].e + b.data[j + 1].e;
            if(v != 0){
                c.data[k + 1].i = a.data[i + 1].i;
                c.data[k + 1].j = a.data[i + 1].j;
                c.data[k + 1].e = v;
                k++;
            }
            i++;
            j++;
        }
      }
      //若行不相同 的两种情况
      else if(i == a.tu || a.data[i + 1].i > b.data[j + 1].i && j != b.tu){
          c.data[k + 1].i = b.data[j + 1].i;
          c.data[k + 1].j = b.data[j + 1].j;
          c.data[k + 1].e = b.data[j + 1].e;
          k++;
          j++;      //前往下一个b的非0元
      }
      else if(j == b.tu || a.data[i + 1].i < b.data[j + 1].i && i != a.tu){   
          c.data[k + 1].i = a.data[i + 1].i;
          c.data[k + 1].j = a.data[i + 1].j;
          c.data[k + 1].e = a.data[i + 1].e;
          k++;
          i++;      //前往下一个a的非0元
      }
    }
    c.tu = k;
}


//乘法辅助函数
int Getval(TSMatrix a, int i, int j){
    int k = 1;     //矩阵三元组下标
    while(k <= a.tu && (a.data[k].i != i || a.data[k].j != j))
        k++;
    if(k <= a.tu)
        return a.data[k].e;
    else
        return 0;
}


//稀疏矩阵三元组乘法
void MultSMatrix(TSMatrix a, TSMatrix b, TSMatrix &c){
    int p = 0;
    ElemType s;
    if(a.nu != b.mu){
       printf("两矩阵无法相乘\n");
       return;
    }

    for(int i = 1; i <= a.mu; i++){
        for(int j = 1; j <= b.nu; j++){
            s = 0;
            for(int k = 1; k <= a.nu; k++)
               s += Getval(a, i, k) * Getval(b, k, j);
            if(s != 0){
               c.data[p + 1].i = i;
               c.data[p + 1].j = j;
               c.data[p + 1].e = s;
               p++;
            }
        }
    }
    c.mu = a.mu;
    c.nu = b.nu;
    c.tu = p;
}


int main(){
   TSMatrix A, B, C, D;
   printf("输入稀疏矩阵A的三元组:\n");
   InPutM(A);
   PrintM(A);
   printf("\n输入稀疏矩阵B的三元组:\n");
   InPutM(B);
   PrintM(B);
   printf("\n矩阵A与B相加得到矩阵C:\n");
   AddSMatrix(A, B, C);
   PrintM(C);
   printf("\n矩阵A与B相乘得到矩阵D:\n");
   MultSMatrix(A, B, D);
   PrintM(D);
}

测试运行结果

标签:零元,int,tu,矩阵,++,加法,数据结构,data,乘法
From: https://www.cnblogs.com/MAKISE004/p/17111813.html

相关文章

  • 数据结构优化建图
    线段树优化建图解决的是这样的一类问题:区间对区间连边,在这类图上做一些事情。(先假设是最短路,这个性质好一些)区间问题会想到线段树。可以想到用线段树建立的虚点做这件事......
  • Golang数据结构
    数据类型不同类型的内存样式图查看变量类型使用fmt.Printfpackagemainimport"fmt"funcmain(){str:="Helloworld"fmt.Printf("%T",str)}使用re......
  • [数据结构] 稀疏矩阵的转置与快速转置
    稀疏矩阵稀疏矩阵的定义在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵。假设在m*n的矩阵中,有t个非0元......
  • 【数据结构】八种常见数据结构介绍
    数据结构是计算机存储、组织数据的方式。一种好的数据结构可以带来更高的运行或者存储效率。数据在内存中是呈线性排列的,但是我们可以使用指针等道具,构造出类似“树形”的......
  • 01 数据结构概念简述
     一、数据结构就是数据的存储方式如何存储、以体现数据之间的逻辑关系,为以后更好的利用数据做准备数据关系一般分为:"一对一"、"一对多"、"多对多""一对一"关系:使......
  • Python学习之线性数据结构(二)
    print(end='')end=表示语句结束后加入的东西print(sep='')sep表示间隔符1223这个间隔的空格就是间隔符print(1,2,sep='',end='')#打印数字1和2间隔符为空格......
  • List集合-数据结构
    List集合-数据结构数据结构是计算机存储,组织数据的方式.是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者......
  • 数据结构
    数组地址的计算1维数组,默认是行优先,也就是先横着放。2位数组行优先,相当于最外围数组横着放,列优先就是最里面的先横着放。稀疏矩阵图(没懂)顺序表和链表队列有......
  • [数据结构] AVL树
    AVL树的基本概念AVL树的定义AVL树得名于它的发明者G.M.Adelson-Velsky和E.M.Landis。AVL树本质上是一颗二叉搜索树,并且本身带有平衡的条件,即每个结点的左右子树的高......
  • 数据结构可视化神器推荐
    旧金山大学做的BPlusTreeVisualization模型​​数据结构可视化​​......