受網際網路衝擊,曾經的“民營超市第一股”人人樂走向沒落
阿新 • • 發佈:2021-07-11
1.順序儲存:三元組表示法、偽地址表示法
2.鏈式儲存:鄰接表表示法、十字連結串列表示法
這裡介紹三元組表示法。
稀疏矩陣
元素結構體定義如下:
1 typedef struct 2 { 3 int val; 4 int i,j; 5 }Trimat; 6 7 //定義一個含有maxterms個非零元素的稀疏矩陣的三元組8 Trimat trimat[maxterms+1];//maxterms是已經定義好的常量
為了簡便起見,可以不使用上述結構體定義,直接申請一個如下的陣列即可:
1 int trimat[maxterms+1][3];
trimat[k] [0]表示原矩陣中的元素按行優先順序的第k個非零元素的值;trimat[k] [1]和trimat[k] [2]表示第k個元素在矩陣中的位置。規定第0行的3個元素分別用來儲存非零元素個數、行數和列數。
建立三元組
1 //A是m*n的稀疏矩陣,B是三元組,maxSize是預先定義好的最大矩陣維數 2 void createTrimat(intA[][maxSize],int m,int n,int B[][3]) 3 { 4 int k=1;//B的行 5 for(int i=0;i<m;i++) 6 { 7 for(int j=0;j<n;j++) 8 { 9 if(A[i][j]!=0)//找到非零元素,放入三元組 10 { 11 B[k][0]=A[i][j]; 12 B[k][1]=i; 13 B[k][2]=j; 14 k++; 15 } 16 } 17 } 18 //三元組第一行資訊 19 B[0][0]=k-1; 20 B[0][1]=m; 21 B[0][2]=n; 22 }
通過三元組列印矩陣
1 void print(int B[][3]) 2 { 3 int k=1; 4 for(int i=0;i<B[0][1];i++) 5 { 6 for(int j=0;j<B[0][2];j++) 7 { 8 if(i==B[k][1]&&j==B[k][2])//(i,j)在三元組中 9 { 10 cout<<B[k][0]<<" "; 11 k++; 12 } 13 else 14 cout<<"0 "; 15 } 16 cout<<endl; 17 } 18 }
測試
1 int main() 2 { 3 int A[maxSize][maxSize]={{0,0,0,1}, 4 {0,0,3,2}, 5 {1,0,0,0}, 6 {0,2,0,0}}; 7 int B[maxterms+1][3]; 8 //稀疏矩陣A 轉 三元組B 9 createTrimat(A,4,4,B); 10 //列印B 11 for(int i=0;i<6;i++) 12 { 13 for(int j=0;j<3;j++) 14 cout<<B[i][j]<<" "; 15 cout<<endl; 16 } 17 cout<<endl; 18 //由B列印A 19 print(B); 20 21 return 0; 22 }
執行
練習
1.假設稀疏矩陣A採用三元組表示,編寫一個函式,計算其轉置矩陣B,要求B也採用三元組表示。
分析:因為三元組內元素是原矩陣按行優先儲存的結果,所以不能僅僅將行下標和列下標互換。B中的元素從上往下的順序是B原矩陣按行從左到右從上到下的順序,因為轉置,B矩陣的第一行是A的第一列,因此正確的做法是找出A的第一列元素,把他們依次放入B的三元組中,然後找A的第二列元素、第三列元素......
1 void transpose(int A[][3],int B[][3]) 2 { 3 //更新B的第一行資訊 4 B[0][0]=A[0][0]; 5 B[0][1]=A[0][2]; 6 B[0][2]=A[0][1]; 7 if(B[0][0]>0) 8 { 9 int q=1;//B的行 10 for(int i=0;i<B[0][1];i++) //B的行數 11 { 12 for(int k=1;k<=B[0][0];k++) 13 { 14 if(A[k][2]==i)//A的列等於B的行 15 { 16 B[q][0]=A[k][0]; 17 B[q][1]=A[k][2]; 18 B[q][2]=A[k][1]; 19 q++; 20 } 21 } 22 } 23 } 24 }
2.假設稀疏矩陣A和B(兩矩陣行列數對應相等)都採用三元組表示,編寫一個函式,計算C=A+B,要求C也採用三元組表示,所有矩陣均為int型。
1 void add(int A[][3],int B[][3],int C[][3]) 2 { 3 4 int i=1,j=1;//i遍歷A,j遍歷B 5 int k=1;//C的行 6 while(i<=A[0][0]&&j<=B[0][0]) 7 { 8 if(A[i][1]==B[j][1])//如果A當前元素的行號等於B當前元素的行號,則比較列號 9 { 10 if(A[i][2]<B[j][2])//A的列號小於B的列號,則將A這個元素寫入C 11 { 12 C[k][0]=A[i][0]; 13 C[k][1]=A[i][1]; 14 C[k][2]=A[i][2]; 15 k++; 16 i++; 17 18 } 19 else if(A[i][2]>B[j][2])//A的列號大於B的列號,則將B這個元素寫入C 20 { 21 C[k][0]=B[j][0]; 22 C[k][1]=B[j][1]; 23 C[k][2]=B[j][2]; 24 k++; 25 j++; 26 } 27 else //A的列號等於B的列號,則將這兩個元素相加,寫入C 28 { 29 int m=A[i][0]+B[j][0]; 30 if(m!=0)//m有可能為0,不為0才寫入C 31 { 32 C[k][0]=m; 33 C[k][1]=A[i][1]; 34 C[k][2]=A[i][2]; 35 k++; 36 37 } 38 i++; 39 j++; 40 } 41 } 42 else if(A[i][1]<B[j][1])//A當前元素的行號小於B當前元素的行號,則將A的這個元素寫入C 43 { 44 C[k][0]=A[i][0]; 45 C[k][1]=A[i][1]; 46 C[k][2]=A[i][2]; 47 k++; 48 i++; 49 } 50 else //A當前元素的行號大於B當前元素的行號,則將B的這個元素寫入C 51 { 52 C[k][0]=B[j][0]; 53 C[k][1]=B[j][1]; 54 C[k][2]=B[j][2]; 55 k++; 56 j++; 57 } 58 } 59 60 while(i<=A[0][0])//A有剩餘元素,B已經處理完畢,將A中元素直接放入C 61 { 62 C[k][0]=A[i][0]; 63 C[k][1]=A[i][1]; 64 C[k][2]=A[i][2]; 65 k++; 66 i++; 67 } 68 69 while(j<=B[0][0])//B有剩餘元素,A已經處理完畢,將B中元素直接放入C 70 { 71 C[k][0]=B[j][0]; 72 C[k][1]=B[j][1]; 73 C[k][2]=B[j][2]; 74 k++; 75 j++; 76 } 77 78 //產生第0行資訊 79 C[0][0]=k-1; 80 C[0][1]=A[0][1]; 81 C[0][2]=A[0][2]; 82 }
3.假設稀疏矩陣A和B(分別為m*n和n*k矩陣)採用三元組表示,編寫一個函式,計算C=A*B,要求C也是採用三元組表示的稀疏矩陣。
1 //返回D對應的稀疏矩陣中(i,j)位置上的值 2 int getValue(int D[][maxSize],int i,int j) 3 { 4 int k=1; 5 whilt(k<=D[0][0]&&(D[k][1]!=i||D[k][2]!=j)) 6 k++; 7 if(k<=D[0][0]) 8 return D[k][0]; 9 else 10 return 0; 11 } 12 //矩陣相乘 13 void mul(int A[][3],int B[][3],int C[][3],int m,int n,int k) 14 { 15 int p=1;//C的行 16 for(int i=0;i<m;i++) 17 { 18 for(int j=0;j<k;j++) 19 { 20 for(int l=0;l<n;l++)//A的第m行乘B的第k列 為 C的(m,k) 21 s+=getValue(A,i,l)+getValue(B,l,j); 22 if(s!=0) 23 { 24 C[p][0]=s; 25 C[p][1]=i; 26 C[p][2]=j; 27 p++; 28 } 29 } 30 } 31 C[0][0]=p-1; 32 C[0][1]=m; 33 C[0][2]=k; 34 }