- 计算机软件技术基础(第2版)
- 李平
- 5267字
- 2021-04-02 04:53:46
3.5 其他线性结构
字符串是一种常见的线性结构。字符串及定义在字符串上的运算是计算机程序进行文字处理的基础。二维数组是数学中的矩阵在程序设计语言中的表示。当矩阵中的绝大部分元素为零时,采用一般的二维数组的存储方式会浪费大量的存储空间,同时也做了大量不必要的运算。因此,本节主要讨论的内容包括:①串的结构特点及其基本操作;②一般二维数据的顺序存储结构,以及当矩阵中大部分为零元素时的表示方法。
3.5.1 串的定义和串的存储方式
1.串的概念
串(String)是零个或多个字符组成的有限序列。一般记为:
S=′a1 a2…an′(n≥0)其中,S是串的名字,用单引号括起来的字符序列是串的值;ai(1≤i≤n)可以是字母、数字或其他字符;n是串中字符的个数,称为串的长度,n=0时的串称为空串(Null String)。
串中任意个连续的字符组成的子序列称为该串的子串,包含子串的串相应地称为主串。通常将字符在串中的序号称为该字符在串中的位置。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。
假如有字符串A=‘data elements’,B=‘elements’,C=‘data’,则它们的长度分别为13、8和4。B和C是A的子串,B在A中的位置是6,C在A中的位置是1。
当且仅当两个字符串的值相等时,称这两个字符串是相等的。即只有当两个字符串的长度相等,并且每个对应位置的字符都相等时才相等。
需要特别指出的是,字符串值必须用一对单引号括起来(C语言中是双引号),但单引号是界限符,它不属于字符串,其作用是避免与变量名或常量混淆。
由一个或多个称为空格的特殊字符组成的串,称为空格串(Blank String),其长度为字符串中空格字符的个数。请注意空串(Null String)和空格串(Blank String)的区别。
字符串也是线性表的一种,因此字符串的逻辑结构和线性表极为相似,区别仅在于字符串的数据对象限定为字符集。
2.串的抽象数据类型定义
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-78.jpg?sign=1739692817-wFsSra9WmCQBl3jDRlfUSWn8oAMHspsQ-0-e78e1382e67c6ef490866b57463b3735)
3.串的基本操作
(1)StrAsign(S,chars)
初始条件:chars是字符串常量。
操作结果:生成一个值等于chars的字符串S。
(2)StrLength(S)
初始条件:字符串S存在。
操作结果:返回字符串S的长度,即字符串S中的元素个数。
(3)StrInsert(S,pos,T)
初始条件:字符串S存在,1≤pos≤StrLength(S)+1。
操作结果:在字符串S的第pos个字符之前插入串T。
(4)StrDelete(S,pos,len)
初始条件:字符串S存在,1≤pos≤StrLength(S)-len+1。
操作结果:从字符串S中删除第pos个字符起长度为len的子串。
(5)StrCopy(S,T)
初始条件:字符串S存在。
操作结果:由字符串T复制得字符串S。
(6)StrEmpty(S)
初始条件:字符串S存在。
操作结果:若字符串S为空串,则返回TRUE,否则返回FALSE。
(7)StrCompare(S,T)
初始条件:字符串S和T存在。
操作结果:若S>T,则返回值>0;如S=T,则返回值=0;若S<T,则返回值<0。
(8)StrClear(S)
初始条件:字符串S存在。
操作结果:将字符串S清为空串。
(9)StrCat(S,T)
初始条件:字符串S和T存在。
操作结果:将字符串T的值连接在字符串S的后面。
(10)SubString(Sub,S,pos,len)
初始条件:字符串S存在,1≤pos≤StrLength(S)且1≤len≤StrLength(S)-pos+1。
操作结果:用Sub返回字符串S的第pos个字符起长度为len的子串。
(11)StrIndex(S,pos,T)
初始条件:字符串S和T存在,T是非空串,1≤pos≤StrLength(S)。
操作结果:若字符串S中存在和字符串T相同的子串,则返回它在字符串S中第pos个字符之后第一次出现的位置;否则返回0。
(12)StrReplace(S,T,V)
初始条件:字符串S,T和V存在,且T是非空串。
操作结果:用V替换字符串S中出现的所有与T相等的不重叠的子串。
(13)StrDestroy(S)
初始条件:字符串S存在。
操作结果:销毁字符串S。
3.5.2 定长顺序串运算
1.定长顺序串
定长顺序串是将字符串设计成一种结构类型,字符串的存储分配是在编译时完成的。和前面所讲的线性表的顺序存储结构类似,用一组地址连续的存储单元存储字符串的字符序列。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-79.jpg?sign=1739692817-D678inIcQSr4tnCA3wA5G6FnXNol3tJz-0-08b8c2b31cd3d4d94e7d5ae713715a7f)
其中,Maxlen表示串的最大长度;ch是存储字符串的一维数组,每个分量存储一个字符;len是字符串的长度。
在进行串的插入时,插入位置pos将字符串分为两部分(假设为A、B,长度为LA、LB),及待插入部分(假设为C,长度为LC),则字符串由插入前的AB变为ACB,可能有3种情况:
1)插入后字符串长(LA+LC+LB)≤Maxlen:则将B后移LC个元素位置,再将C插入。
2)插入后字符串长>Maxlen且pos+LC<Maxlen:则B后移时会有部分字符被舍弃。
3)插入后字符串长>Maxlen且pos+LC>Maxlen:则B的全部字符被舍弃(不需后移),并且C在插入时也有部分字符被舍弃。
在进行串的连接时(假设原来串为A,长度为LA,待连接串为B,长度为LB),也可能有3种情况:
1)连接后字符串长≤Maxlen:则直接将B加在A的后面。
2)连接后字符串长>Maxlen且LA<Maxlen:则B会有部分字符被舍弃。
3)连接后字符串长>Maxlen且LA=Maxlen:则B的全部字符被舍弃(不需连接)。
置换时的情况较为复杂,假设为原字符串为A、长度为LA,被置换字符串为B、长度为LB,置换字符串为C、长度为LC,每次置换位置为pos,则每次置换有3种可能:
1)LB=LC:将C复制到A中pos起共LC个字符处。
2)LB>LC:将A中B后的所有字符前移LB-LC个字符位置,然后将C复制到A中pos起共LC个字符。
3)LB<LC:将A中B后的所有字符后移LC-LB个字符位置,然后将C复制到A中pos起共LC个字符,此时可能会出现串插入时的3种情况,应按情况作相应处理。
下面是定长顺序串部分基本操作的实现。
2.串插入函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-80.jpg?sign=1739692817-skiWE3E7jZWzqnadVmNHlMcJe0D4vbrf-0-97516dd83700af1e177338d53eab63d1)
3.串删除函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-82.jpg?sign=1739692817-QF7FBu6wsiwZHocZ8bWxAWSibypc7akk-0-1bc57ded3291474d42bd932777df8bc1)
4.串复制函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-83.jpg?sign=1739692817-WX0LWs8m6khD8HJ946JFsLAfShDpnwBz-0-c83767ac7c743010c1b8eddef081b243)
5.判空函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-84.jpg?sign=1739692817-UusfDwmq6bJSjspvMhuc93Sj6Oq6Ic0k-0-7b695427fe00de65e89f09b0b01b6b13)
6.串比较函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-86.jpg?sign=1739692817-Fn6XQqPY9UehIjX4YSzCkXsSsjMCKrkv-0-835ea25827cf1de56714685ed907cdb7)
7.求串长函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-87.jpg?sign=1739692817-17ZleWdfnr4LgWre9juCcVblcZfwWMiy-0-2b7665941df92e377cc0daa909d14eee)
8.清空串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-88.jpg?sign=1739692817-76U5Yc8c1vaw60nDJJkM9b7mkywwRjhX-0-ce28946985251b23cc52524b01c27833)
9.联接串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-89.jpg?sign=1739692817-0Qij7xQydmcb18P5dugOiSyGOZLsQXpI-0-0cbbaa0911b06719d134128efa0aa8f9)
10.求子串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-90.jpg?sign=1739692817-F4j5ZHhQLHh0Eo8mkalm4rCUssAHFuGa-0-1b8c3ccd6b90a09dd9afd16b221d4866)
11.定位函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-91.jpg?sign=1739692817-XW96X0M6DYqsotlurrsA6WpxyXkSb82x-0-876396e7bb9bf9b483e9ce9eb4e24c38)
3.5.3 二维数组的结构特点和存储方式
数组已广泛应用于各种高级语言中,是比较常用的一种数据结构。从结构上看,它是线性表的推广。这一讲主要介绍数组的逻辑结构定义及存储方式,着重介绍特殊形式的数组——稀疏矩阵的存储结构及相应的运算。
1.数组的定义和运算
一维数组
A=(a1,a2,…an)
二维数组
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-92.jpg?sign=1739692817-PkoWBbs8C4OmzKCRjFNdxr28o5KQY0ad-0-bf4680e60bcc689d77b6f2ba75c898b1)
一般形式二维数组
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-93.jpg?sign=1739692817-djkGeTYzJmIJFFkm3Lunv3MjjaJoxr4k-0-dffa4c78039ccf9f4fc87216d953c262)
数组结构具有3个性质:
●数据元素数目固定,即一旦说明了一个数组结构,其元素数目不再有增减变化。
●数据元素具有相同的类型。
●数据元素的下标关系具有上下界的约束并且下标有序。
对于数组,通常只有以下两种运算:
●给定一组下标,存取相应的数据元素。
●给定一组下标,修改相应数据元素中的某个数据项的值。
2.数组的顺序存储结构
由于计算机的存储单元是一维结构,而数组是多维结构,要用一维的连续单元存放数组的元素,就有存放次序的约定问题。根据不同的存放形式可以分为以下几种类型。
(1)按行优先顺序存放
按行优先顺序存放就是按行切分,如上述二维数组A23,按行切分可得如图3-19所示存放顺序。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-94.jpg?sign=1739692817-TkGZVV7oJ7wvdKUnunvAEF9gRAPZamW9-0-45782b08dc74f3125451e21fd92ebdd7)
图3-19 按行优先二维数组存放示意图
假设每个元素仅占一个存储单元,则元素aij的存储地址可以通过下面的关系式计算:
Loc(aij)=Loc(a11)+(i-1)×n+(j-1) (1≤i≤m,1≤j≤n) (3-5)
对应二维数组按行优先顺序存放,在三维数组中是以左下标为主序的存储方式。例如Almp(设l=2,m=3,n=4),如图3-20所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-95.jpg?sign=1739692817-dEzcNSvOGpFMVoPHhwKY6MfyPYqUV1bS-0-7bede94e56f1d314416adafd5ca0a7f2)
图3-20 按行优先三维数组存放示意图
元素aijk的存储地址可以通过下面的关系式计算:Loc(aijk)=Loc(a111)+(i-1)×m×n+(j-1)×n+(k-1)(1≤i≤l,1≤j≤m,1≤k≤n)
(3-6)
在C、BASIC、COBOL和Pascal等语言中,数组的实现采用按行优先的存储方式。利用存储地址、指针,可以提高数据访问的效率。
例如,C语言中,一维数组时:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-96.jpg?sign=1739692817-UNV3swFTdER59XV7nBM4dPtUKni1Huzn-0-dc6dbc7f47c2427521d09d3d96e5bb55)
要访问第5个元素,可以采用下面写法:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-97.jpg?sign=1739692817-Mra1uaXJuk1IFA7gCTHDDGNgU4PkFYxv-0-1994045595dc64ec7b158364ddff55a3)
二维数组时:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-98.jpg?sign=1739692817-bXQprux6GrdkcbJ0YtfA00eGznF8FqEC-0-f13684daa876ca88ea1e395bf832b9c5)
要访问a32=9,则
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-99.jpg?sign=1739692817-Z3uP1elzFrPu9dkobaIyGUEsGjilXdjJ-0-18040c5a0a6d25ab0637c5776b7866e4)
(2)按列优先顺序存放
如果数组按列切分,就得到按列优先顺序存放方式,仍以上述二维数组A23为例,按列切分可得如图3-21所示存放顺序。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-100.jpg?sign=1739692817-gCYgimd6eJ6h7tsMBXlkQcodwBuB7Uf9-0-d54238aa2b860decd179df0ce1fea9a4)
图3-21 按列优先二维数组存放示意图
假设每个元素仅占一个存储单元,则元素aij的存储地址可以通过下面的关系式计算:
Loc(aij)=Loc(a11)+(j-1)×m+(i-1)(1≤i≤m,1≤j≤n)(3-7)
对应二维数组按列优先顺序存放,在三维数组中是以右下标为主序的存储方式。例如,Almn(设l=2,m=3,n=4),如图3-22所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-101.jpg?sign=1739692817-Gylsv62n4yz4Pckf4cPwFsNvZNcsOCiz-0-0cbeffd361d4ab4eef76b86a48009f12)
图3-22 按列优先三维数组存放示意图
元素aijk的存储地址可以通过下面的关系式计算:Loc(aijk)=Loc(a111)+(k-1)×l×m+(j-1)×l+(i-1)(1≤i≤l,1≤j≤m,1≤k≤n)
(3-8)
在FORTRAN语言中,数组采用按列优先的存储方式。
3.特殊矩阵的存储方式
上述两种数组的顺序存储方式,对于绝大部分元素值不为零的数组是合适的。但是,如果数组中有很多元素的值为零时,上述存储方式会造成大量存储单元的浪费。
(1)下三角阵的存储方式
设下三角阵数组Ann为
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-102.jpg?sign=1739692817-lVGxjLdh26vKNU2i4ThaXNcyLTtx6XnH-0-68c605c639ac6e84f17b4f1bb21a3532)
若将其中非零元素按行优先顺序存放,则
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-103.jpg?sign=1739692817-6r6e0cDRQHhtbHIvNs7tjRXRIKGaPGgN-0-fd800df419c7a30ca3ab8a56ae1e57d4)
从第1行至第i-1行的非零元素个数为
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-104.jpg?sign=1739692817-xssIe3GO7YdVA69Ai42ytruDdLfsmX4X-0-58e3a0b6b2d37f236633448e6fcf2a7f)
求取其中非零元素aij地址的关系式为:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-105.jpg?sign=1739692817-Pf9j90AoV0WXMHjdgHc1EBqsmHl5fqL8-0-d9132750f1f5c7b0a2400328b3cc1448)
(2)三对角阵的存储方式
设Ann为三对角阵:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-106.jpg?sign=1739692817-UtXMoEz0OvMoS4oqbQERkvbNF7w79juJ-0-34a3bf3e763ffc4d2263e62134413d4c)
若将其中非零元素按行优先顺序存放,则
{a11,a12,a21,a22,a23,a32,a33,a34,…,an,n-1,ann}求取其中非零元素aij地址的关系式为:
Loc(aij)=Loc(a11)+2(i-1)+(j-1)
(i=1,j=1,2或i=n,j=n-1,n或1<i<n,j=i-1,i,i+1)
(3-10)
(3)对称矩阵的存储方式
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-107.jpg?sign=1739692817-Pz8GOUnlBfVc4OLCpXb97lmphqIrs506-0-7e0c59919222d637bf24c44650a6860a)
类似三对角阵的存储。
4.稀疏矩阵
矩阵在科学计算中应用十分广泛,而且随着计算机应用的发展,大量出现处理高阶矩阵问题,有的甚至达到几十万阶、几千亿个元素,这就远远超过计算机的内存容量。然而,在大量的高阶问题中,绝大部分元素是零值。当非零元素所占比例小于等于25%~30%时,我们称这种含有大量零元素的矩阵为稀疏矩阵。压缩这种零元素占据的空间,不但能节省内存空间,而且能够避免大量零元素进行的无意义运算,大大提高运算效率。
(1)顺序存储结构
1)三元组表。线性表中的每个结点由3个字段组成,分别是该非零元素的行下标、列下标和值,按行优先顺序排列。以下讨论矩阵下标均从1开始。
C语言中数据类型:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-108.jpg?sign=1739692817-aYD2yEWApCczJCVl6ZG9MsQjRdLBZdez-0-63f27b829b1f418a096c826ca67c5335)
稀疏矩阵用三元组表示的例子如图3-23所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-109.jpg?sign=1739692817-Yq6WqaqU4ZfEWWkBhpfRbGdp2DfcbWnr-0-bccca0eac5d88172487a7b9013894010)
图3-23 矩阵和三元组表示
若行下标、列下标与值均占一个存储单元,非零元素个数为N,那么这种方法需要3N个存储单元,由于是按行优先顺序存放,因此行下标排列是递增有序的,在检索数组元素时若用对半检索方法,则存取一个元素的时间为O(log2N)。
2)伪地址表示法。伪地址是指本元素在矩阵中(包含零元素在内)按行优先顺序的相对位置,上述稀疏矩阵A中非另元素的伪地址为:
{2,5,6,8,12,16}
查找元素:伪地址=n×(i-1)+j,n为矩阵的列数。
例,查找a23=3,a23的伪地址=5×(2-1)+3=8。由计算得到的伪地址和伪地址表,即可查到a23的值。
伪地址表示法共需2N个存储单元,但要花费时间计算伪地址。
(2)顺序存储结构稀疏矩阵的转置运算
转置是一种最简单的矩阵运算,一般矩阵的转置算法为:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-110.jpg?sign=1739692817-4RIzHXRHw4tiuixfXP3tKwZ5FP2Jk8Pv-0-9b0d7a3b6aa3a8a315d110ed9b7aa15f)
它的执行时间为O(m×n)。由于稀疏矩阵含有大量的零元素,这种方法显然不经济。以下介绍三元组表的转置算法。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-111.jpg?sign=1739692817-tkGgzkVZzNMh690PbYvxiAnm36k0WYtg-0-129c949745dde944876a346ffc168877)
它的执行时间为O(t×n)。由于非零元素个数t远远大于行数,故三元组转置算法虽然节省了空间,但浪费了时间。
(3)链接存储结构
顺序存储结构的缺点是当非零元素的位置或个数经常变动时,即要进行的元素的插入或删除将会带来诸多不便,这时采用链表结构更为恰当。
1)带行指针向量的单链表表示。本方法设置一个行指针向量,向量中每一个元素为一指针类型,指向本行矩阵的第1个非零元素结点,若本行无非零元素,则指针为空。例如,对上述矩阵A的单链表表示如图3-24所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-113.jpg?sign=1739692817-7lJOHP6n6Z6xBQ1lnKZM94PBvOUd4Z1V-0-d2cb7f3e7db37d5f2c4bb69927528fad)
图3-24 矩阵A带行指针向量的单链表表示
若矩阵的行数为m,非零元素个数为N,则它的存储量为3N+m;若每一行中的非零元素个数为s,则存取元素的时间复杂度为O(s)。
2)十字链表结构。在十字链表中,存放表头结点和非零元素结点的结构相似,如图3-25所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-114.jpg?sign=1739692817-W0FfDnJ29eaX0RTxdzfhC5CPnKdgJXDH-0-c23e89d67ea3804d571c6f69737c4a5c)
图3-25 十字链表结构
例如,对上述矩阵建立十字链表
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-115.jpg?sign=1739692817-q85KLgttKhWzg3UDRNjfit30uSwRVt5e-0-ede7d59e642fd685c4fcac562c87e55c)
建立链表表头,如图3-26所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-116.jpg?sign=1739692817-zQNUUKKX2xO8KrhBx3kWLYJaBRfqO9Td-0-04630984eb80165e302f4a01b8118d98)
图3-26 十字链表表头
插入非零结点,行、列构成循环链表,如图3-27所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-117.jpg?sign=1739692817-N3fPftwPihOFfizfddGMaFPflArewVTn-0-82449a2e091ec52efb517b912f088282)
图3-27 插入非零结点后的十字链表
增加附加头结点,头结点中row、col分别存放稀疏矩阵的行数和列数,并将所有表头构成循环链表,如图3-28所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-118.jpg?sign=1739692817-BOZE7yb6yyHqnsY9P4imwLZAotvHr2rs-0-7c4fb9f374a2e7449422fcf85a27f18a)
图3-28 增加附加头结点的十字链表
3.5.4 矩阵和特殊矩阵元素的存储结构与应用实例
【问题描述】
设已知一个n×n的上三角矩阵X,其上三角元素已按行序为主序连续存放在数组Y中。
请设计一个tran函数,将数组Y中元素按列为主序连续存放在数组Z中。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-119.jpg?sign=1739692817-kKXP2b1BLTcdkbIAn9zPRo838xOBP8b7-0-892857c5f76fe9ff3976c75fd9d79f71)
Y=(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
Z=(1,2,6,3,7,10,4,8,1,13,5,9,12,14,15)
【算法分析】
解题思路:用i和j表示矩阵X中元素的行和列下标。用k表示矩阵Y中元素的下标,初始时i=1,j=1,k=1;将y[k]=x[i,j]元素存放在z[j(j-1)+i]中,且当一行没有结束时j++,否则i++并修改下一行元素的个数及i和j的值,直到k=n(n+1)/2为止。
C语言源程序如下:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-120.jpg?sign=1739692817-uQgZTCVkrqWcYzTgtufcmVep52Shxaux-0-500cf5db6f47dc823bfd044f4143dd57)
3.5.5 稀疏矩阵的压缩存储方式和简单运算实例
【问题描述】
输入一个稀疏矩阵A,①将其转化为三元组的表示形式;②在三元组存储矩阵中查找值为x的结点是否存在于矩阵A中,如果存在,输出其位置,否则输出“不存在”提示信息。
【算法分析】
稀疏矩阵用二维数组A进行存储,三元组用结构体B表示。先将A数组中的非0元素及它所在的行、列位置信息按行优先顺序存储到B中,然后再在B中查找值为x的结点所在位置,如果存在,输出其位置,否则输出“不存在”提示信息。
C语言源程序如下:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-122.jpg?sign=1739692817-QHMt1gbvMeEvqxt5Ua2e3C8zXBfXhVHf-0-e89ce66ccee5bd5de72490e8801c0313)