稀疏矩阵转置+快速转置

稀疏矩阵转置

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 }

原文地址:https://www.cnblogs.com/jiamian/p/11669046.html

时间: 2024-11-10 13:29:44

稀疏矩阵转置+快速转置的相关文章

【数据结构之旅】稀疏矩阵的快速转置

说明: 稀疏矩阵的快速转置算法的核心在于,用一个数组num记录原来矩阵中的每列非零元个数,用另一个数组cpos来记录原矩阵每列第一个非零元在新矩阵中的位置,以此来达到快速转置的目的. 用这样的方法,主要是希望,矩阵转置后,存储顺序依然是按照行来存储的. 1.实现及代码注释 根据上面的核心提示,可以有如下的代码,下面的代码中的注释已经非常详细,因此这里就不把每一部分实现的功能独立开来了: #include<stdio.h> #include<stdlib.h> #define OVE

稀疏矩阵三元组快速转置(转poklau123写的很清楚)

关于稀疏矩阵的快速转置法,首先得明白其是通过对三元表进行转置.如果误以为是对矩阵进行转置,毫无疑问就算你想破脑袋也想不出个所以然,别陷入死胡同了! 对于一个三元表,行为i,列为j,值为v.需将其i与j的值对调才能得到新的三元表,但是如果直接进行转换,得到的新的三元表的顺序是混乱的,不符合三元表的规则.所以,课本首先介绍了一个用扫描来转置的算法(这个算法比较容易,在这里我就不说了),但是这个转置算法的时间复杂度太高,于是就有了接下来的快速转置算法. 要你对一个三元表进行步骤最少的转置,你可能会想,

数据结构----稀疏矩阵的快速转置

使用两种方法将稀疏矩阵快速转置 #include<iostream> #include<vector> using namespace std; template<class T> struct Triple  //三元组 { size_t row; size_t col; T _value; }; template<class T> class SparseMatrix { public: SparseMatrix(T *arr, size_t rowsi

稀疏矩阵-压缩存储-列转置法- 一次定位快速转置法

稀疏矩阵的压缩存储 压缩存储值存储极少数的有效数据.使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放. 压缩存储:行优先一行一行扫 有效数据存入以为矩阵_arr 列转置法 : 从前向后遍历压缩矩阵,先找列号为0的存入 转置矩阵的压缩矩阵.然后从前向后找列号为1的 ...直到转置矩阵的压缩矩阵大小和 原矩阵的一样大 这时就找完了 时间复杂度为    O(原矩阵列数 * 压缩矩阵长度) 一次定位快速转置法: 设置两个辅助矩阵 RowCou

稀疏矩阵的压缩存储及快速转置

当一个矩阵为稀疏矩阵时,有效数据的个数比无效数据要少得多,因此若将一个矩阵全部存储会浪费空间,可以只将有效数据存储起来,无效数据作为标记 代码如下: #include <iostream> #include <vector> using namespace std; //可用一个三元组来存储有效数据的信息 template<class T> struct Triple {  size_t _row;  size_t _col;  T _value; }; //系数矩阵类

稀疏矩阵的列序递增法和一次定位快速转置法

稀疏矩阵:矩阵中大多数元素为0的矩阵,从直观上讲,当非零元素个数低于总元素的30%时,这样的矩阵为稀疏矩阵. 如: int array [6][5] =     {{1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; 稀疏矩阵的压缩存储:使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放

稀疏矩阵的普通转置与快速转置算法

稀疏矩阵的普通转置与快速转置算法 一般来说,对于系数矩阵,我们使用三元组来存储.即就是将矩阵的所有非零元素的三元组存放在一个顺序表中,如图所示: 注意一个转置的前提:该顺序表是排好序的,即行优先,列其次. 一.普通转置 这种算法比较简单,也很容易想到: 算法思想: 对M.data从头至尾扫描: ?第一次扫描时,将M.data中列号为1的三元组赋值到T.data中 ?第二次扫描时,将M.data中列号为2的三元组赋值到T.data中 ?依此类推,直至将M.data所有三元组赋值到T.data中 代

C++实现稀疏矩阵的压缩存储、转置、快速转置

/*稀疏矩阵的压缩存储.转置.快速转置*/ #include <iostream> using namespace std; #include <vector> //三元组 template<class T> struct Triple { size_t _row; size_t _col; T _value; Triple(size_t row = 0, size_t col = 0, const T& value = T()) :_row(row) ,_co

c++矩阵的转置和快速转置

矩阵的转置 将原矩阵的行.列对换,也就是将[i][j]和[j][i]位置上的数据对换. 程序代码: #include<vector>   //稀疏矩阵push pop operator[] 和顺序表一致   template<class T> struct Triple  //定义一个三元组 可以直接访问的定义成struct { size_t _row; size_t _col; T _value;   Triple(size_t row, size_t col, const T&