zoukankan      html  css  js  c++  java
  • 稀疏矩阵转置+快速转置

    稀疏矩阵转置  

    Description

    稀疏矩阵的存储不宜用二维数组存储每个元素,那样的话会浪费很多的存储空间。所以可以使用一个一维数组存储其中的非零元素。这个一维数组的元素类型是一个三元组,由非零元素在该稀疏矩阵中的位置(行号和列号对)以及该元组的值构成。

    矩阵转置就是将矩阵行和列上的元素对换。

    现在就请你对一个稀疏矩阵进行转置。以下是稀疏矩阵转置的算法描述:

    图:稀疏矩阵转置的算法描述

    Input

    输入的第一行是两个整数r和c(r*c <= 12500),分别表示一个包含很多0的稀疏矩阵的行数和列数。接下来有r行,每行有c个整数,表示这个稀疏矩阵的各个元素。

    Output

    输出c行,每行有r个整数,每个整数后跟一个空格。该结果为输入稀疏矩阵的转置矩阵。

    Sample Input

    6 7
    0 12 9 0 0 0 0
    0 0 0 0 0 0 0
    -3 0 0 0 0 14 0
    0 0 24 0 0 0 0
    0 18 0 0 0 0 0
    15 0 0 -7 0 0 0

    Sample Output

    0 0 -3 0 0 15 
    12 0 0 0 18 0 
    9 0 0 24 0 0 
    0 0 0 0 0 -7 
    0 0 0 0 0 0 
    0 0 14 0 0 0 
    0 0 0 0 0 0 

    HINT

    提示:

    严老师纸质书中用union类型来表示稀疏矩阵类型,这是有问题的,应该使用struct来表示该类型。

    注意理解为什么转置算法中,以列从小到大来进行转置。实际上只需一个循环就能够完成转置而不需将列从小到大来处理,转置后的矩阵虽然是正确的但却乱掉了,以至于在各种处理中会增加复杂。(其实就本题而言,如果不以列从小到大处理将导致输出困难,输出的复杂度增加)

    总结:

    矩阵是一个应用很广泛的工具和课题。看看《黑客帝国》就知道了。现在初步给大家介绍矩阵的操作,以后有机会还会详细讨论矩阵的。

      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 #include <math.h>  
     13 const int INF=0x3f3f3f3f;  
     14 typedef long long LL;  
     15 const int mod=1e9+7;  
     16 const int maxn=1e4+10;  
     17 using namespace std;  
     18     
     19 typedef struct
     20 {  
     21     int row;  
     22     int col;   
     23     int val;   
     24 }Triple;  
     25     
     26 typedef struct
     27 {  
     28     Triple date[maxn];  
     29     int rows;
     30     int cols;
     31     int nums;
     32 }TSMatrix;  
     33     
     34 void TransposeTSMatrix(TSMatrix *A,TSMatrix *B)  
     35 {  
     36     B->rows=A->cols;  
     37     B->cols=A->rows;  
     38     B->nums=A->nums;  
     39     if(B->nums > 0)  
     40     {  
     41         int cnt=0;  
     42         for(int i=1;i<=A->cols;i++)  
     43         {  
     44             for(int j=1;j<=A->nums;j++)  
     45             {  
     46                 if(A->date[j].col==i)  
     47                 {  
     48                     cnt++;  
     49                     B->date[cnt].row=A->date[j].col;  
     50                     B->date[cnt].col=A->date[j].row;  
     51                     B->date[cnt].val=A->date[j].val;  
     52                 }  
     53             }  
     54             if(cnt == B->nums)  
     55                 break;  
     56         }  
     57     }  
     58     return ;  
     59 }  
     60     
     61 int main()  
     62 {  
     63     TSMatrix A,B;  
     64     scanf("%d %d",&A.rows,&A.cols);  
     65     A.nums=0;  
     66     for(int i=1;i<=A.rows;i++)  
     67     {  
     68         for(int j=1;j<=A.cols;j++)  
     69         {  
     70             int x;  
     71             scanf("%d",&x);  
     72             if(x)  
     73             {  
     74                 A.nums++;  
     75                 A.date[A.nums].row=i;  
     76                 A.date[A.nums].col=j;  
     77                 A.date[A.nums].val=x;  
     78             }     
     79         }  
     80     }  
     81     TransposeTSMatrix(&A,&B);  
     82     int cnt=1;  
     83     for(int i=1;i<=B.rows;i++) 
     84     {  
     85         for(int j=1;j<=B.cols;j++)  
     86         {  
     87             int a,b;  
     88             a=B.date[cnt].row;  
     89             b=B.date[cnt].col;  
     90             if(a==i&&b==j)  
     91             {  
     92                 printf("%d ",B.date[cnt].val);  
     93                 cnt++;  
     94             }  
     95             else
     96                 printf("%d ",0);  
     97         }  
     98         printf("
    ");  
     99     }  
    100     return 0;  
    101 } 

    稀疏矩阵快速转置 

    Description

    稀疏矩阵的存储不宜用二维数组存储每个元素,那样的话会浪费很多的存储空间。所以可以使用一个一维数组存储其中的非零元素。这个一维数组的元素类型是一个三元组,由非零元素在该稀疏矩阵中的位置(行号和列号对)以及该元组的值构成。
    而矩阵转置就是将矩阵行和列上的元素对换。参考算法5.1中的具体做法,令mu和nu分别代表稀疏矩阵的行数和列数,不难发现其时间复杂度为O(mu×nu)。而当非零元的个数tu与mu×nu同数量级时,算法5.1的时间复杂度将上升至O(mu×nu2)。因此,需要采用快速的稀疏矩阵转置算法。
    现在就请你实现一个快速的对稀疏矩阵进行转置的算法。以下是稀疏矩阵快速转置的算法描述:

    Input

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

    Output

    输出为读入的稀疏矩阵的转置矩阵。输出共有c行,每行有r个整数,每个整数后输出一个空格。请注意行尾输出换行。

    Sample Input

    6 7
    0 12 9 0 0 0 0
    0 0 0 0 0 0 0
    -3 0 0 0 0 14 0
    0 0 24 0 0 0 0
    0 18 0 0 0 0 0
    15 0 0 -7 0 0 0

    Sample Output

    0 0 -3 0 0 15 
    12 0 0 0 18 0 
    9 0 0 24 0 0 
    0 0 0 0 0 -7 
    0 0 0 0 0 0 
    0 0 14 0 0 0 
    0 0 0 0 0 0 

    HINT

    提示:

    这个算法仅比算法5.1多用了两个辅助向量。对于这个算法的时间复杂度,不难发现算法中有4个并列的单循环,循环次数分别为nu和tu,因而总的时间复杂度为O(nu+tu)。而当稀疏矩阵的非零元个数tu和mu×nu的数量级相同时,其时间复杂度为O(mu×nu),与经典算法的时间复杂度相同。

    请注意理解为什么转置算法中,以列从小到大来进行转置。实际上只需一个循环就能够完成转置而不需将列从小到大来处理,转置后的矩阵虽然内容正确,但元素的顺序却发生了变化,以至于在后续的各种处理操作中会增加复杂度。而在本题中,如果不按照列从小到大的顺序处理将导致输出困难,大大增加输出的复杂度。

    总结:

    稀疏矩阵是矩阵应用中很重要的一部分,由于其元素稀疏的特殊性质,我们可以得到比传统矩阵算法更快速的特殊算法。这也将会在本章后面的题目中得到体现。
      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+10;  
     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 rows;//矩阵的总行数
     29     int cols;//矩阵的总列数
     30     int nums;//矩阵的非零元素个数
     31 }TSMatrix;
     32 
     33 //void TransposeTSMatrix(TSMatrix *A,TSMatrix *B)//矩阵的转置
     34 //{
     35 //    B->rows=A->cols;  
     36 //    B->cols=A->rows;  
     37 //    B->nums=A->nums;  
     38 //    if(B->nums > 0)  
     39 //    {  
     40 //        int cnt=0;  
     41 //        for(int i=1;i<=A->cols;i++)  
     42 //        {  
     43 //            for(int j=1;j<=A->nums;j++)  
     44 //            {  
     45 //                if(A->data[j].col==i)  
     46 //                {  
     47 //                    cnt++;  
     48 //                    B->data[cnt].row=A->data[j].col;  
     49 //                    B->data[cnt].col=A->data[j].row;  
     50 //                    B->data[cnt].val=A->data[j].val;  
     51 //                }  
     52 //            }  
     53 //            if(cnt == B->nums)  
     54 //                break;  
     55 //        }  
     56 //    }  
     57 //    return ;  
     58 //}  
     59 
     60 int num[maxn];
     61 int pos[maxn];//转置后第col行的开始位置
     62 
     63 void Fast_TransposeTSMatrix (TSMatrix *A,TSMatrix *B)
     64 {
     65     B->rows=A->cols;  
     66     B->cols=A->rows;  
     67     B->nums=A->nums;
     68     pos[1]=1;
     69     if(B->nums)
     70     {
     71         memset(num,0,sizeof(num));
     72         for(int i=1;i<=A->nums;i++)
     73             num[A->data[i].col]++;
     74         for(int col=2;col<=A->cols;col++)
     75             pos[col]=pos[col-1]+num[col-1];
     76         for(int i=1;i<=A->nums;i++)
     77         {
     78             int t=A->data[i].col;
     79             B->data[pos[t]].row=A->data[i].col;
     80             B->data[pos[t]].col=A->data[i].row;
     81             B->data[pos[t]].val=A->data[i].val;
     82             pos[t]++;
     83         }
     84     }
     85 }
     86 
     87 int main()  
     88 {  
     89     TSMatrix A,B;  
     90     scanf("%d %d",&A.rows,&A.cols);  
     91     A.nums=0;  
     92     for(int i=1;i<=A.rows;i++)  
     93     {  
     94         for(int j=1;j<=A.cols;j++)  
     95         {  
     96             int x;  
     97             scanf("%d",&x);  
     98             if(x)  
     99             {  
    100                 A.nums++;  
    101                 A.data[A.nums].row=i;  
    102                 A.data[A.nums].col=j;  
    103                 A.data[A.nums].val=x;  
    104             }     
    105         }  
    106     }
    107     Fast_TransposeTSMatrix(&A,&B); 
    108     int cnt=1; 
    109     for(int i=1;i<=B.rows;i++)//输出转置后的矩阵   
    110     {  
    111         for(int j=1;j<=B.cols;j++)  
    112         {  
    113             int a,b;  
    114             a=B.data[cnt].row;  
    115             b=B.data[cnt].col;  
    116             if(a==i&&b==j)  
    117             {  
    118                 printf("%d ",B.data[cnt].val);  
    119                 cnt++;  
    120             }  
    121             else  
    122                 printf("%d ",0);  
    123         }  
    124         printf("
    ");  
    125     }  
    126     return 0;
    127 }
  • 相关阅读:
    leetcode-剑指10-OK
    leetcode-剑指22-OK
    vue组件引入
    vue项目单页
    vue-cli脚手架创建vue项目
    vue生命周期
    ES6 DEMO
    ES6
    记录一个天坑
    CentOS 7防火墙快速开放端口配置方法
  • 原文地址:https://www.cnblogs.com/jiamian/p/11669046.html
Copyright © 2011-2022 走看看