当前位置: 首页 > news >正文

第6章串数组:稀疏矩阵的十字链表表示

6.7.3 十字链表

稀疏矩阵的三元组顺序表,是用顺序存储结构存放稀疏矩阵。此外,稀疏矩阵也可以链式存储结构表示。以如下稀疏矩阵为例:

M=[30050−1002000] \pmb{M}=\begin{bmatrix}3&0&0&5\\0&-1&0&0\\2&0&0&0\end{bmatrix} M=302010000500

如果要存储其中的非零元素,显然必须要说明该元素所在的行、列以及数值,也就是结点结构中应该有行、列和非零元素的值。但是,如果结点仅仅是这样的结构,还无法构成“链”,若要构成链式结构,必须要有“指针”指示当前非零元素的“后继”非零元素。矩阵中每个非零元的“后继”非零元,可能是与它在同一行、也有可能是在同一列。所以,每个结点还必须包括两个域:

  • 向右域 right:用以链接同一行中下一个非零元。
  • 向下域:down:用以链接同一列中下一个非零元。

如图 6.7.3 所示,即为表示稀疏矩阵链式存储结构中的一个结点的结构示意图。

在这里插入图片描述

图 6.7.3 稀疏矩阵链式存储结构

按照这种结点设计,矩阵 M\pmb{M}M 中的非零元素就可以表示为图 6.7.4 所示的存储方式,同一行的非零元通过 right 域链接成一个线性链表,同一列的非零元通过 down 域链接成一个线性链接,每个非零元既是某个行链表中的一个结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表,故称这样的存储结构为十字链表

在这里插入图片描述

图 6.7.4 稀疏矩阵中非零元素的链式存储

在十字链表中的每个行链表和列链表,可以用之前学过的单链表或循环单链表表示。

每个单链表都有一个头指针,因此对于十字链表中的行链表和列链表,每个链表也都有一个头指针。于是,用两个一维数组,分别存储行链表的头指针和列链表的头指针,最终得到如图 6.7.5 所示的存储结构示意图。

在这里插入图片描述

图 6.7.5 表示稀疏矩阵的十字链表

按照上述示意图,就可以写出表示稀疏矩阵的十字链表的存储结构:

typedef struct OLNode{int i, j; //非零元的行下标、列下标ElemType e; //非零元数值struct OLNode * right, * down; //非零元所在行表和列表的后继链域
}OLNode; * OLink; //非零元结点typedef struct{OLink * rhead, *chead; //行和列链表头指针向量基址int mu, nu, tu; //稀疏矩阵的行数、列数和非零元个数
}CrossList; 

根据图 6.7.5 可以知道,十字链表本质上就是以前所学过的链表的综合,因此,如果要将一个稀疏矩阵存储为十字链表的结构,也就是不断地向行链表或者列链表中插入新的非零元素所对应的结点。

Status CreateSMatrixOL(CrossList &M){//创建稀疏矩阵 M,采用十字链表存储表示if(M) free(M); //判断 M 是否已经存在,如果存在就不再创建scanf(&m, &n, &t); //输入 M 的行数、列数和非零元个数M.mu = m;M.nu = n;M.tu = t;if (!(M.rhead = (OLink *) malloc((m+1) * sizeof(OLink))))exit(OVERFLOW);if (!(M.chead = (OLink *) malloc((n+1) * sizeof(OLink))))exit(OVERFLOW);M.rhead[] = M.chead[] = NULL;//初始化行列头指针向量;各行列链表为空链表for (scanf(&i, &j, &e)); i != 0; scanf(&i, &j, &e){//按任意次序输入非零元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){//i 行链表空 //或输入的列号小于行表的首元结点的列下标//则该结点做插入到头指针后,即作为新的首元结点//此处使用单链表p->right = M.rhead[i];//M.rhead[i]为NULL或原首元结点M.rhead[i] = p;//头指针指向 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;
}

【算法分析】

上述算法对非零元输入的先后次序没有任何要求。每建立一个非零元的结点,都要寻査它在行表和列表中的插入位置。若矩阵 M\pmb{M}Mm×nm\times nm×n ,且有 ttt 个非零元,则算法的时间复杂度为 O(t×max⁡{m,n})O(t\times\max\{m,n\})O(t×max{m,n})

http://www.dtcms.com/a/434896.html

相关文章:

  • 【STM32项目开源】基于STM32的工地环境监测系统
  • 手机登录网站怎么建设如何做一个网站代码
  • 解决django.db.utils.OperationalError: attempt to write a readonly database错误
  • CAN-超时计数器(Timeout Counter)
  • 网站建设策划有哪些建设网站用英文怎么说
  • 报告派研读:2025年光学光电子深度报告
  • 技术演进中的开发沉思-121Linux命令篇:系统设置命令(下)
  • 深入理解 JavaScript 闭包与作用域
  • 【操作系统-Day 38】LRU的完美替身:深入解析时钟(Clock)页面置换算法
  • Linux 入门指南:从零掌握基础文件与目录操作命令
  • 高职院校高水平专业建设网站wordpress的windows
  • 网络原理-HTTPS
  • 马鞍山网站建设文如何查网站注册信息
  • 郑州机械网站建设memcached wordpress 慢 卡
  • Java数据结构:ArrayList与顺序表2
  • python系统设计2-选题
  • 做网站表示时间的控件用哪个wordpress 新窗口打开文章
  • Phase 与 Invisibility 的区别
  • MATLAB学习文档(二十三)
  • 基于php网站开发手机官网
  • 2018 年真题配套词汇单词笔记(考研真相)
  • Portainer实战:轻松搭建Docker可视化管理系统
  • PostgreSql FDW 与 DBLINK 区别
  • 若依ry替换mybatis为mybatis-plus
  • 深圳做微商网站企业网站托管收费标准
  • 怎样做影视网站不侵权站群系统哪个好用
  • 项目中HTTP协议处理部分
  • 二元锦标赛:进化算法中的选择机制及其应用
  • 2026新选题-基于Python的老年病医疗数据分析系统的设计与实现(数据采集+可视化分析)
  • Linux权限核心:chmod命令终极指南(文字与数字法详解)