矩阵及其十字链表结构
作者:互联网
-
产生背景
矩阵的非零元个数和位置在操作过程中变化较大,不再适合采用顺序三元组
表示。因此产生了一种用链式存储结构
来表示三元组的线性表。 -
使用十字链表来表示矩阵
1、矩阵中每个非零元可用一个含有5个域的结点来表示:i,j,e
表示该非零元所在的行数,列数,元素值;向右域right
用以链接同一行中下一个非零元;向下域down
用以链接同一列中下一个非零元。
2、每个非零元同时是某个行列表或者列链表的结点,把一个矩阵转化成了一个十字交叉的链表。
3、可用两个一维数组来表示,分别存储行链表的头指针和列链表的头指针。
-
稀疏矩阵的十字链表表示
//一个非零元的结构
typedef struct OLNode
{
int i,j;//非零元所在行数,列数
ElemType e;//非零元元素值
struct OLNode *right, *down;//该非零元所在行表和列表的后继链域
}OLNode, *OLink;
//一个稀疏矩阵的十字链表结构
typedef struct
{
OLink *rhead, *chead;//行列链表的头指针向量,头节点
int mu, nu, tu;//稀疏矩阵的行数,列数,非零元个数
}CrossList;
- 创建一个十字链表来表示稀疏矩阵
Status CreateCrossMatrix(CrossList &M)
{
if(M)
{
free(M);
}
scanf(&M.mu, &M.nu, &M.tu);
if(!(M.rhead = (OLink* )malloc((M.mu+1)*sizeof(OLink))))
{
exit(OVERFLOW);
}
if(!(M.chead = (OLink* )malloc((M.nu+1)*sizeof(OLink))))
{
exit(OVERFLOW);
}
M.rhead[] = NULL;
M.chead[] = NULL;
for(scanf(&i, &j, &e); i!=0; scanf(&i, &j, &e))
{
if(!(p = (OLink)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
{
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
{
for(q = M.chead[j];
(q->down) && (q->down->i<i);
q = q->down);
p->down = q->down;
q->down = p;
}
}
return OK;
}
此算法的时间复杂度为 O( t * max{ m, n } )
每建立一个非零元的结点时都要查询它在行表和列表的插入位置
十字矩阵
实现两个稀疏矩阵
相加
STATUS AddCrossList(CrossList &A, CrossList B)
{
//初始化两个辅助量
pre = NULL;
for(int j=1; j<=A.nu; j++)
{
hl[j]=A.chead[j];
}
for(row=1; row<A.mu; row++)
{
pa = A.rhead[row];
pb = B.rhead[row];
while(pb)
{
if(pa == NULL || pa->j > pb->j)
{
// 只要pb非空,必然要将pb结点加到
// pa中,并将pb结点从它的行链表中
// 删除,只删行链表为了判断本行加
// 操作是否结束.
p = pb;
pb = pb->right;
//这个if处理行链表的链接改动
if(pre == NULL)
{
A.rhead[row] = p;
}
else
{
// pre哪来的?
// 注意后面对pre的处理
pre->right = p;
}
p->right = pa;
pre = p;
// 这个if处理列链表的改动
if(!A.chead[p->j] || \
A.chead[p->j]->i > p->i)
{
p->down = A.chead[p->j];
A.chead[p->j] = p;
}
else
{
while(hl[p->j]->down && \
hl[p->j]->i < p->i)
{
hl[p->j] = hl[p->j]->down;
}
p->down = hl[p->j]->down;
hl[p->j]->down = p;
}
hl[p->j] = p;
}
else if(pa != NULL && pa->j < pb->j)
{
pre = pa;
pa = pa->right;
}
else if(pa->j == pb->j)
{
p = pb;
pb = pb->right;
pa->e += p->e;
if(pa->e == 0)
{
//删去这个结点
//这个if从行链表删除该节点
if(pre == NULL)
{
A.rhead[pa->i] = pa->right;
}
else
{
pre->right = pa->right;
}
//从列链表删除该节点
while(hl[p->j]->down != pa)
{
hl[p->j] = hl[p->j]->down;
}
hl[p->j]->down = pa->down;
free(pa);
}
}
}
}
return OK;
}
标签:down,right,矩阵,pb,链表,零元,pa,十字 来源: https://blog.csdn.net/engineer0/article/details/111351558