zoukankan      html  css  js  c++  java
  • 行逻辑链接的矩阵乘法

    Description

    对于一个稀疏矩阵,当需要频繁的随机存取任意一行的非零元时,则需要知道每一行的第一个非零元在三元组表中的位置。为此,可以将算法5.2中用来指示“行”信息的辅助数组cpot固定在稀疏矩阵的存储结构中。这种“带行链接信息”的三元组表即为行逻辑链接的顺序表。其类型描述如下:
     
    针对存储于行逻辑链接顺序表的稀疏矩阵,其矩阵相乘的算法与经典算法有所不同。因此,对于两个稀疏矩阵相乘(Q=M×N)的过程可以大致描述如下:
     
    请使用行逻辑链接的顺序表实现两个稀疏矩阵的乘法。

    Input

    输入的第一行是两个整数r1和c1(r1<200, c1<200, r1*c1 <= 12500),分别表示一个包含很多0的稀疏矩阵的行数和列数。接下来有r1行,每行有c1个整数,用空格隔开,表示第一个稀疏矩阵的各个元素。
    之后的一行有两个整数r2和c2(c1=r2<200, c2<200, r2*c2 <= 12500),分别表示一个包含很多0的稀疏矩阵的行数和列数。接下来有r2行,每行有c2个整数,用空格隔开,表示第二个稀疏矩阵的各个元素。

    Output

    输出两个矩阵的乘积。输出共有r1行,每行有c2个整数,每个整数后输出一个空格。请注意行尾输出换行。

    Sample Input

    4 5
    0 0 0 69 78
    0 0 5 0 0
    0 0 0 0 0
    0 91 2 0 82
    5 6
    0 18 0 0 0 0
    0 0 67 0 0 0
    0 0 0 0 0 41
    0 0 47 62 0 0
    0 0 0 0 0 35

    Sample Output

    0 0 3243 4278 0 2730 
    0 0 0 0 0 205 
    0 0 0 0 0 0 
    0 0 6097 0 0 2952 

    HINT

    提示:

    对于稀疏矩阵M和N,其相乘的基本操作是:对于M中每个元素M.data[p](p=1,2,...,M.tu),找到N中所有满足条件M.data[p].j=N.data[q].i的元素N.data[q],从而求得M.data[p]与M.data[q]的乘积。需要注意的是,这个乘积只是Q[i][j]中的一部分,需要将其累加从而得到最终的结果。

    另外需要注意的是,两个稀疏矩阵相乘的乘积并不一定是稀疏矩阵。

    总结:

    采用行逻辑链接的顺序表通过使用非零元的行信息,使稀疏矩阵的存储和使用效能进一步提高。尤其是对于稀疏矩阵相乘, 这种算法省去了非常多无谓的计算。
      1 #include <stdio.h>  
      2 #include <string.h>  
      3 #include <iostream>  
      4 #include <string>  
      5 #include <math.h>  
      6 #include <algorithm>  
      7 #include <vector>  
      8 #include <stack>  
      9 #include <queue>  
     10 #include <set>  
     11 #include <map>
     12 const int INF=0x3f3f3f3f;  
     13 typedef long long LL;
     14 const int mod=1e9+7;
     15 const int maxn=1e4+2510;  
     16 using namespace std;  
     17   
     18 typedef struct  
     19 {  
     20     int row;//
     21     int col;//
     22     int val;//
     23 }Triple;  
     24   
     25 typedef struct  
     26 {  
     27     Triple data[maxn];//三元组
     28     int rpos[maxn];//每一行的第一个非零元在三元组表中的位置
     29     int rows;//矩阵的总行数
     30     int cols;//矩阵的总列数
     31     int nums;//矩阵的非零元素个数
     32 }Matrix;
     33 
     34 void MulMatrix(Matrix A,Matrix B,Matrix *C)
     35 {
     36     if(A.cols!=B.rows)//如果矩阵A的列数与矩阵B的行数不等,则不能做矩阵乘运算
     37         return ;
     38     C->rows=A.rows;
     39     C->cols=B.cols;
     40     C->nums=0;
     41     if(A.nums*B.nums==0)//如果其中任意矩阵的元素个数为零,做乘法元素没有意义,全是0
     42         return ;
     43     int ccol;
     44     for(int arow=1;arow<=A.rows;arow++)
     45     {
     46         int temp[maxn]={0};//创建一个临时存储乘积结果的数组,且初始化为0,遍历每次都需要清空
     47         C->rpos[arow]=C->nums+1;
     48         int tp;
     49         if(arow<A.rows)
     50             tp=A.rpos[arow+1];//获取矩阵A的下一行第一个非零元素在data数组中位置
     51         else
     52             tp=A.nums+1;//若当前行是最后一行,则取最后一个元素+1
     53         //遍历当前行的所有的非0元素
     54         for(int p=A.rpos[arow];p<tp;p++)
     55         {
     56             int brow=A.data[p].col;//取该非0元素的列数,便于去B中找对应的做乘积的非0元素
     57             int t;
     58             // 判断如果对于A中非0元素,找到矩阵B中做乘法的那一行中的所有的非0元素
     59             if(brow<B.rows)
     60                 t=B.rpos[brow+1];
     61             else
     62                 t=B.nums+1;
     63             //遍历找到的对应的非0元素,开始做乘积运算
     64             for(int q=B.rpos[brow];q<t;q++)
     65             {
     66                 //得到的乘积结果,每次和temp数组中相应位置的数值做加和运算
     67                 ccol=B.data[q].col;
     68                 temp[ccol]+=A.data[p].val*B.data[q].val;
     69             }
     70         }
     71         //矩阵C的行数等于矩阵A的行数,列数等于矩阵B的列数,所以,得到的temp存储的结果,也会在C的列数的范围内
     72         for(ccol=1;ccol<=C->cols;ccol++)
     73         {
     74             //由于结果可以是0,而0不需要存储,所以在这里需要判断
     75             if(temp[ccol])
     76             {
     77                 C->nums++;
     78                 if(C->nums > maxn)
     79                     return;
     80                 C->data[C->nums].val=temp[ccol];
     81                 C->data[C->nums].row=arow;
     82                 C->data[C->nums].col=ccol;
     83             }
     84         }
     85     }
     86 }
     87 
     88 int main()  
     89 {
     90     Matrix A,B,C;
     91     scanf("%d %d",&A.rows,&A.cols);
     92     A.nums=0;
     93     for(int i=1;i<=A.rows;i++)
     94     {
     95         A.rpos[i]=A.nums+1;
     96         for(int j=1;j<=A.cols;j++)
     97         {
     98             int x;
     99             scanf("%d",&x);
    100             if(x)
    101             {
    102                 A.nums++;  
    103                 A.data[A.nums].row=i;
    104                 A.data[A.nums].col=j;
    105                 A.data[A.nums].val=x;
    106             }
    107         }
    108     }
    109     scanf("%d %d",&B.rows,&B.cols);  
    110     B.nums=0;
    111     for(int i=1;i<=B.rows;i++)  
    112     { 
    113         B.rpos[i]=B.nums+1;
    114         for(int j=1;j<=B.cols;j++)  
    115         {  
    116             int x;  
    117             scanf("%d",&x);  
    118             if(x)  
    119             {  
    120                 B.nums++;  
    121                 B.data[B.nums].row=i;  
    122                 B.data[B.nums].col=j;  
    123                 B.data[B.nums].val=x;  
    124             }
    125         }
    126     }
    127     MulMatrix(A,B,&C); 
    128     int cnt=1; 
    129     for(int i=1;i<=C.rows;i++)//输出转置后的矩阵   
    130     {
    131         for(int j=1;j<=C.cols;j++)
    132         {
    133             int a,b;
    134             a=C.data[cnt].row;
    135             b=C.data[cnt].col;
    136             if(a==i&&b==j)
    137             {
    138                 printf("%d ",C.data[cnt].val);
    139                 cnt++;
    140             }
    141             else
    142                 printf("%d ",0);
    143         }
    144         printf("
    ");
    145     }
    146     return 0;
    147 }
  • 相关阅读:
    快速登录机器&数据库
    质量报告之我见
    一些 ssh 小技巧
    virtualenv简介以及一个比较折腾的scrapy安装方法
    用scrapy数据抓取实践
    即将到来的5G,我们该做些什么准备?
    浅谈由管理者角色引出的B端产品设计思考点
    CodeForces 707C Pythagorean Triples (数论)
    UVaLive 6625 Diagrams & Tableaux (状压DP 或者 DFS暴力)
    CodeForces 707B Bakery (水题,暴力,贪心)
  • 原文地址:https://www.cnblogs.com/jiamian/p/11669020.html
Copyright © 2011-2022 走看看