在链表中,每个非零元可以用含有5个域的结点来表示,其中i,j,e分别表示非零元的行标,列标,值,向右域right用以链接同一行中的下一个非零元,向下域用以链接同一列中的下一个非零元。同一行中的非零元通过right域链接成一个线性链表,同一列中的非零元通过down域链接成一个线性链表,每个非零元即是某个行链接表中的结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表,故称这样的存储结构为十字链表,可用两个分别存储行链表的头指针和列链表的头指针一维数组表示之。
构造十字链表矩阵的代码如下:
//稀疏矩阵的十字链表存储表示
typedef int ElemType;
typedef struct OLNode{
int i,j; //行标和列标
ElemType e;
struct OLNode *right,*down;
OLNode(){
i=j=0;
e=0;
right=NULL;
down=NULL;
}
}OLNode,*OLink;
typedef struct CrossList{
OLink *rhead,*chead; //行和列链表头指针向量基址由CreateSMatrix分配
int mu,nu,tu; //矩阵行数,列数,非零元个数
CrossList(){
rhead=NULL;
chead=NULL;
mu=nu=tu=0;
}
}CrossList;
Status CreateSMatrix_OL(CrossList &M){
//创建稀疏矩阵M。采用十字链表存储表示
cout<<"please input 'mu','nu','tu' :";
int m,n,t;
cin>>m>>n>>t;
if(t>m*n) return ERROR;
M.mu=m; M.nu=n; M.tu=t;
if(!(M.rhead=(OLink*)malloc(M.mu*sizeof(OLink)))) exit(OVERFLOW);
if(!(M.chead=(OLink*)malloc(M.nu*sizeof(OLink)))) exit(OVERFLOW);
//M.rhead[]=M.chead[]=NULL; //初始化行列头指针向量;各行列链表为空链表
for(int k=0;k<M.mu;++k){
M.rhead[k]=NULL;
}
for(int k=0;k<M.nu;++k){
M.chead[k]=NULL;
}
int i,j;
ElemType e;
for(cin>>i>>j>>e;i!=0;cin>>i>>j>>e){//按任意次序输入非零元
OLNode* p;
if(!(p=(OLNode*)malloc(sizeof(OLNode)))) exit(OVERFLOW);
p->i=i; p->j=j; p->e=e; //生成结点
if(M.rhead[i]==NULL||M.rhead[i]->j>j){
p->right=M.rhead[i];
M.rhead[i]=p;
}else{//寻查在行表中的插入位置
OLNode* q=NULL;
for(q=M.rhead[i];(q->right)&&q->right->j<j;q=q->right);
p->right=q->right;
q->right=p;
}//完成行插入
if(M.chead[j]==NULL||M.chead[j]->i>i){
p->down=M.chead[j];
M.chead[j]=p;
}else{//寻查在行表中的插入位置
OLNode* q=NULL;
for(q=M.chead[j];(q->down)&&q->down->i<i;q=q->down);
p->down=q->down;
q->down=p;
}//完成列插入
}
return OK;
}
int main()
{
CrossList m;
CreateSMatrix_OL(m);
return 0;
}