稀疏矩阵转置+快速转置

风格不统一 提交于 2019-12-01 07:28:23

稀疏矩阵转置  

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("\n");     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("\n");    125     }    126     return 0;  127 }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!