矩阵之间能够进行加法运算的前提条件是:各矩阵的行数和列数必须相等。
在行数和列数都相等的情况下,矩阵相加的结果就是矩阵中对应位置的值相加所组成的矩阵,例如:
采用链式存储结构存储稀疏矩阵三元组的方法,称为“十字。
十字链表法表示矩阵
例如,用十字链表法表示矩阵 A ,为:
图2 矩阵用十字链表法表示
由此可见,采用十字链表表示矩阵时,矩阵的每一行和每一个列都可以看作是一个单独的链表,而之所以能够表示矩阵,是因为行链表和列链表都分别存储在各自的
图 2 中:存储行链表的数组称为 rhead 数组;存储列链表的数组称为 chead 数组。
十字链表中的结点
从图2中的十字链表表示矩阵的例子可以看到,十字链表中的结点由 5 部分组成:
图3 十字链表中的结点
指针域A存储的是矩阵中结点所在列的下一个结点的地址(称为 “down域”);
指针域B存储的是矩阵中该结点所在行的下一个结点的地址(称为 “right域”);
用结构体自定义表示为:
typedef struct OLNode
{
int i,j,e; //矩阵三元组 i 代表行 j 代表列 e 代表当前位置的数据
struct OLNode *right,*down; //指针域 右指针 下指针
}OLNode,*OLink;
十字链表的结构
使用十字链表表示一个完整的矩阵,在了解矩阵中各结点的结构外,还需要存储矩阵的行数、列数以及非 0 元素的个数,另外,还需要将各结点链接成的链表存储在数组中。
所以,采用结构体自定义十字链表的结构,为:
typedef struct
{
OLink *rhead,*chead; //存放各行和列链表头指针的数组
int mu,nu,tu; //矩阵的行数,列数和非零元的个数
}CrossList;
十字链表存储矩阵三元组
由于三元组存储的是该数据元素的行标、列标和数值,所以,通过行标和列标,就能在十字链表中唯一确定一个位置。
判断方法为:在同一行中通过列标来判断位置;在同一列中通过行标来判断位置。
首先判断该数据元素 A(例如三元组为:(i,j,k))所在行的具体位置:
如果 A 的列标 j 值比该行第一个非 0 元素 B 的 j 值小,说明该数据元素在元素 B 的左侧,这时 A 就成为了该行第一个非0元素(也适用于当该行没有非 0 元素的情况,可以一并讨论)
如果 A 的列标 j 比该行第一个非 0 元素 B 的 j 值大,说明 A 在 B 的右侧,这时,就需要遍历该行链表,找到插入位置的前一个结点,进行插入。
对应行链表的位置确定之后,判断数据元素 A 在对应列的位置:
如果 A 的行标比该列第一个非 0 元素 B 的行标 i 值还小,说明 A 在 B 的上边,这时 A 就成了该列第一个非 0 元素。(也适用于该列没有非 0 元素的情况)
反之,说明 A 在 B 的下边,这时就需要遍历该列链表,找到要插入位置的上一个数据元素,进行插入。
实现代码:
//创建系数矩阵M,采用十字链表存储表示
CrossList CreateMatrix_OL(CrossList M)
{
int m,n,t;
int i,j,e;
OLNode *p,*q;//定义辅助变量
scanf("%d%d%d",&m,&n,&t); //输入矩阵的行列及非零元的数量
//初始化矩阵的行列及非零元的数量
M.mu=m;
M.nu=n;
M.tu=t;
if(