采用十字链表存储的稀疏矩阵
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 }