1. 程式人生 > 資訊 >受網際網路衝擊,曾經的“民營超市第一股”人人樂走向沒落

受網際網路衝擊,曾經的“民營超市第一股”人人樂走向沒落

稀疏矩陣就是矩陣中分佈著很多零元素(零元素個數遠遠大於非零元素個數),如果將這個矩陣的每個元素都一一儲存,那是很浪費空間的。因此,可以採用一些特殊的儲存結構來儲存它。有以下幾種方法:

1.順序儲存:三元組表示法、偽地址表示法

2.鏈式儲存:鄰接表表示法、十字連結串列表示法

這裡介紹三元組表示法。

稀疏矩陣

三元組資料結構為一個長度為n,表內每個元素都有3個分量的線性表,其3個分量分別為值、行下標和列下標

元素結構體定義如下:

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(int
A[][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  }