Description
當矩陣的非零元個數和位置在操作過程中變化較大時,就不宜采用順序存儲的結構來表示三元組的線性表了。因此,在這種情況下,采用鏈式存儲結構表示三元組更為恰當。十字鏈表就是能夠實現這樣功能的一種數據結構。
在十字鏈表中,每個非零元可以用一個包含5個域的結點表示。其中i、j和e這3個域分別表示該非零元所在的行、列和非零元的值,向右域right用來鏈接同一行中下一個非零元,而向下域down用來鏈接同一列中下一個非零元。同一行的非零元通過right域鏈接成一個線性鏈表,同一列的非零元通過down域鏈接成一個線性鏈表。每個非零元既是某個行鏈表中的一個結點,又是某個列鏈表中的一個結點,整個矩陣通過這樣的結構形成了一個十字交叉的鏈表。
稀疏矩陣的十字鏈表類型可以描述如下:
下面是建立稀疏矩陣十字鏈表的算法描述:
給出一個稀疏矩陣,請將其存儲到一個十字鏈表中,並將存儲完畢的矩陣輸出。
Input
輸入的第一行是兩個整數r和c(r<200, c<200, r*c <= 12500),分別表示一個包含很多0的稀疏矩陣的行數和列數。接下來有r行,每行有c個整數,用空格隔開,表示稀疏矩陣的各個元素。
Output
輸出讀入的矩陣。輸出共有r行,每行有c個整數,每個整數后輸出一個空格。請注意行尾輸出換行。
Sample Input
5 6 0 18 0 0 0 0 0 0 67 0 0 0 0 0 0 0 0 41 0 0 47 62 0 0 0 0 0 0 0 35
Sample Output
0 18 0 0 0 0 0 0 67 0 0 0 0 0 0 0 0 41 0 0 47 62 0 0 0 0 0 0 0 35
HINT
提示:
對於m行n列且有t個非零元的稀疏矩陣,算法5.4的執行時間為O(t×s),其中s=max(m,n)。這是由於每建立一個非零元結點時,都需要通過遍歷查詢它所在的行表和列表中的插入位置。這是因為我們采用的算法實際上對於非零元的輸入先后次序並沒有要求,而如果能夠保證非零元是按照以行序為主序的順序輸入的話,則可以將十字鏈表的建立過程修改為O(t)復雜度的。
總結:
采用十字鏈表存儲的稀疏矩陣適用於矩陣中的非零元個數和位置經常發生變化或變化較大的情況,鏈式結構使得數據的插入、修改和刪除變得十分容易。
十字鏈表原理我在網上找了一個圖:

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+2510; 16 using namespace std; 17 18 typedef struct OLNode 19 { 20 int row; 21 int col; 22 int val; 23 OLNode *right,*down; 24 }OLNode,*OLink; 25 26 typedef struct 27 { 28 OLink *rhead,*chead; 29 int rows; 30 int cols; 31 int nums; 32 }CrossList; 33 34 void CreateSMatrix_OL(CrossList *M) 35 { 36 scanf("%d %d",&M->rows,&M->cols); 37 M->nums=0; 38 M->rhead=(OLink*)malloc((M->rows+1)*sizeof(OLink)); 39 M->chead=(OLink*)malloc((M->cols+1)*sizeof(OLink)); 40 for(int i=1;i<=M->rows;i++) 41 M->rhead[i]=NULL; 42 for(int j=1;j<=M->cols;j++) 43 M->chead[j]=NULL; 44 for(int i=1;i<=M->rows;i++) 45 { 46 for(int j=1;j<=M->cols;j++) 47 { 48 int x; 49 scanf("%d",&x); 50 if(x) 51 { 52 M->nums++; 53 OLink p,q; 54 p=(OLink)malloc(sizeof(OLNode)); 55 p->row=i; 56 p->col=j; 57 p->val=x; 58 p->right=NULL; 59 p->down=NULL; 60 if(M->rhead[i]==NULL||M->rhead[i]->col > j) 61 { 62 p->right=M->rhead[i]; 63 M->rhead[i]=p; 64 } 65 else 66 { 67 for(q=M->rhead[i];(q->right)&&(q->right->col < j);q=q->right); 68 p->right=q->right; 69 q->right=p; 70 } 71 if(M->chead[j]==NULL||M->chead[j]->row > i) 72 { 73 p->down=M->chead[j]; 74 M->chead[j]=p; 75 } 76 else 77 { 78 for(q=M->chead[j];(q->down)&&(q->down->row < i);q=q->down); 79 p->down=q->down; 80 q->down=p; 81 } 82 } 83 } 84 } 85 } 86 87 void Show(CrossList M) 88 { 89 OLink pt; 90 for(int i=1;i<=M.rows;i++) 91 { 92 pt=M.rhead[i]; 93 for(int j=1;j<=M.cols;j++) 94 { 95 if(pt&&pt->col==j) 96 { 97 printf("%d ",pt->val); 98 pt=pt->right; 99 } 100 else 101 printf("%d ",0); 102 } 103 printf("\n"); 104 } 105 } 106 107 int main() 108 { 109 CrossList M; 110 CreateSMatrix_OL(&M); 111 Show(M); 112 return 0; 113 }
