数据结构学习笔记二

数据结构学习笔记二

数组与结构(1)

一、ADT稀疏矩阵

1、存储结构

a、三元组

我想稀疏的矩阵的定义我就不需要说了吧,如果有人不知道的,请查询线性代数。

如果直接用二维数组来存储矩阵,确实是很方便的,其逻辑结构和存储结构雷同,易于处理各种操作,简单直观。但是,如果是稀疏矩阵呢?很显然,如果稀疏矩阵很大的话,就浪费了大量的存储空间(所有为零的元素),实在很不经济。为此,我们可以用一个三元组的数据结构来表示三元组:

稀疏矩阵之所以浪费空间,是因为有大量的重复的零元素占着内存空间,却并没有什么实际作用,于是我们只需要保存所有的非零元素,这样就能节省大量存储单元了,但是要如何保存才能保证矩阵原来的逻辑结构不被打乱?要确定矩阵中任意一个非零元素的信息,需要三个量:元素的行号、元素的列号和元素的值,这就像二维坐标系中的横坐标和纵坐标,用来确定一个点的位置。这里我们用行号和列号来确定元素的位置。既然如此,我们的三元组的存储结构就出来了,只要存储每一个非零元素的行号、列号和元素值这三个量就行了。我们只需要定义一个结构体,结构体中包含以上三个量,再用该结构体定义一个数组,用来存储所有的非零元素。其中,这个数组是按照系数矩阵的行号由小到大排列的。(详细代码后面给出)

b、十字链表

三元组好是好,但也有它的缺点,它的缺点就是,三元组数组是按照行序排列的,这样也是为了方便在矩阵上的各种操作,但也给添加和删除元素带来不便,每次添加和删除元素都要移动其他的元素,这大大增加了程序的开销。如何避免这样的情况呢?自然而然就联想到了数组和链表的关系,链表就是为了解决数组增加删除操作的不便性而产生的,于是,此处我们可以采用链表的存储结构来存储稀疏矩阵的非零元素。具体做法是:链表中的每个结点有5个域,行号、列号、元素值、向右指针和向下指针。如图所示:

 

稀疏矩阵中同一行的非零元素通过right指针域按“列号顺序”链接成一个线性链表,同一列的非零元素则通过down指针域按“行号顺序”链接成一个线性表。这样每个元素既是某个行链表中的一个结点,同时又是某个列链表中的一个结点,每个结点好像在一个十字路口上,所以称为十字链表法。(在这个可能会有点绕人,大家可以看下面给出的图)为了正确表示这种复杂的链表结构,我们还需要另外引入两个一维数组,分别存储各个行链表的头指针和各个列链表的头指针,然后用这两个数组表示十字链表,如图所示:

 

2、存储结构上的操作算法

a、三元组

矩阵本身有很多的运算,我在这只列出其中最长用的一些运算,并在三元组的基础上用算法实现它:转置、加法、减法、乘法。

转置:

朴素转置:

用三元组存储的矩阵转置其实是很简单的,只需要把三元组的行号和列号交换就是了。但是,三元组数组是按照行号顺序排列下来的,这意味着,在进行转置之后的数组将是乱序的。解决这样的个问题有两种做法:

1、在进行交换的时候按照列的顺序来交换,这样就能保证转置后的矩阵是按照行序的。

2、进行交换的时候按照行序,转置完后对新的的数组进行排序,但此时的排序是有两个关键字的,行序和列序。

不管采用以上哪种方式,都是必须嵌套两层循环的,即时间复杂度是平方级的,开销太大了。

有没有办法把时间复杂度降低到线性级的了?这就引出下面要介绍的快速转置算法:

快速转置:

快速转置的思想是,进过一次扫描就能生成转置矩阵且不需要附加的修改。其实要达到这个目的,也是很容易的,

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值