稀疏矩陣轉置+快速轉置


稀疏矩陣轉置  

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×nu 2)。因此,需要采用快速的稀疏矩陣轉置算法。
現在就請你實現一個快速的對稀疏矩陣進行轉置的算法。以下是稀疏矩陣快速轉置的算法描述:

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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM