十字链表法,十字链表压缩存储稀疏矩阵详解
例如,A 和 B 分别为两个矩阵,在实现 "将矩阵 B 加到矩阵 A 上" 的操作时,矩阵 A 中的元素会发生很大的变化,之前的非 0 元素可能变为 0,而 0 元素也可能变为非 0 元素。对于此操作的实现,之前所学的压缩存储方法就显得力不从心。
本节将学习用十字链表存储稀疏矩阵,该存储方式采用的是 "链表+数组" 结构,如图 1 所示。

图 1 十字链表示意图
可以看到,使用十字链表压缩存储稀疏矩阵时,矩阵中的各行各列都各用一各链表存储,与此同时,所有行链表的表头存储到一个数组(rhead),所有列链表的表头存储到另一个数组(chead)中。
因此,各个链表中节点的结构应如图 2 所示:

图 2 十字链表的节点结构
两个指针域分别用于链接所在行的下一个元素以及所在列的下一个元素。
链表中节点的 C 语言代码表示应为:
typedef struct OLNode{
int i,j;//元素的行标和列标
int data;//元素的值
struct OLNode * right,*down;//两个指针域
}OLNode;
同时,表示十字链表结构的 C 语言代码应为:
#include<stdio.h>
#include<stdlib.h>
typedef struct OLNode
{
int i, j, e; //矩阵三元组i代表行 j代表列 e代表当前位置的数据
struct OLNode *right, *down; //指针域 右指针 下指针
}OLNode, *OLink;
typedef struct
{
OLink *rhead, *chead; //行和列链表头指针
int mu, nu, tu; //矩阵的行数,列数和非零元的个数
}CrossList;
CrossList CreateMatrix_OL(CrossList M);
void display(CrossList M);
int main()
{
CrossList M;
M.rhead = NULL;
M.chead = NULL;
M = CreateMatrix_OL(M);
printf("输出矩阵M:\n");
display(M);
return 0;
}
CrossList CreateMatrix_OL(CrossList M)
{
int m, n, t;
int i, j, e;
OLNode *p, *q;
printf("输入矩阵的行数、列数和非0元素个数:");
scanf("%d%d%d", &m, &n, &t);
M.mu = m;
M.nu = n;
M.tu = t;
if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink))))
{
printf("初始化矩阵失败");
exit(0);
}
for (i = 1; i <= m; i++)
{
M.rhead[i] = NULL;
}
for (j = 1; j <= n; j++)
{
M.chead[j] = NULL;
}
for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {
if (!(p = (OLNode*)malloc(sizeof(OLNode))))
{
printf("初始化三元组失败");
exit(0);
}
p->i = i;
p->j = j;
p->e = e;
//链接到行的指定位置
if (NULL == M.rhead[i] || 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 (NULL == M.chead[j] || 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 M;
}
void display(CrossList M) {
for (int i = 1; i <= M.nu; i++)
{
if (NULL != M.chead[i])
{
OLink p = M.chead[i];
while (NULL != p)
{
printf("%d\t%d\t%d\n", p->i, p->j, p->e);
p = p->down;
}
}
}
}
运行结果:
输入矩阵的行数、列数和非0元素个数:3 3 3
2 2 3
2 3 4
3 2 5
0 0 0
输出矩阵M:
2 2 3
3 2 5
2 3 4
- 随机文章
- 东方马尔代夫菜谱(探索东方美食:马尔代夫料理佳肴菜单)
- 马尔代夫主要城市(马尔代夫主要城市:探访仙境般的马累 重写标题:探访马尔代夫首都马累)
- 东航马尔代夫签证(东航推出方便快捷的马尔代夫签证服务)
- 参加马尔代夫婚礼(浪漫梦幻!在马尔代夫举办的完美婚礼)
- 万州马尔代夫新闻(万州马尔代夫火热招募,等你来加入!)
- 上海到马尔代夫要(上海始发到马尔代夫的航线及预订攻略)
- 厦门地税马尔代夫(厦门地税员工赴马尔代夫开展税收活动)
- 印度拖鞋马尔代夫(印度拖鞋入侵马尔代夫:当地居民抗议)
- 印度动武马尔代夫(印度派军舰向马尔代夫,引发地区紧张)
- 海边照片马尔代夫(马尔代夫海滩美照,让你瞬间心旷神怡)
- 民间秘密马尔代夫(探秘马尔代夫:解读岛国的神秘与魅力)
- 清晨马尔代夫的画(清晨的马尔代夫:一个美不胜收的画。)
- 溧阳马尔代夫在哪(溧阳哪里有类似马尔代夫的度假胜地?)
- 苏梅 马尔代夫(苏梅和马尔代夫:旅游胜地最新风向)
- 磁县打卡马尔代夫(磁县百姓走进马尔代夫,探秘海洋世界)
- 惠州马尔代夫图片(惠州这家水上乐园真的很像马尔代夫!)
- 明星评价马尔代夫(明星赞誉马尔代夫:天堂般的度假天地)
- 中国 小马尔代夫(中国建设的小马尔代夫)
- 海南马尔代夫美景(探寻海南最美景色:仿若身临马尔代夫)
- 美丽玉溪马尔代夫(玉溪:“中国马尔代夫”彰显绿色美丽)
- 湖北石首马尔代夫(石首市一夫妻携手将马尔代夫推向高峰)
- 辉县马尔代夫鱼种(辉县领养珍贵马尔代夫鱼成为新兴爱好)
- 辉县马尔代夫救人(辉县勇士援马尔代夫,成功救援落水者)
- 重庆马尔代夫汤泉(重庆汤泉打造马尔代夫式温泉度假胜地)
- 野生马尔代夫海参(马尔代夫神秘生物:野生海参揭开面纱)
- 遇见马尔代夫图片(醉人的马尔代夫:绝美海岛与璀璨阳光)
- 马尔代夫云南大使(马尔代夫驻云南大使就职仪式隆重举行)
- 马尔代夫亮点特色(探索马尔代夫:独特吸引力和美丽经典)
- 马尔代夫上海转机(从马尔代夫到上海再转机:旅行小贴士)
- 马尔代夫万豪集团(马尔代夫万豪集团推出新一轮度假优惠)
