![计算机软件技术基础(第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/297/31304297/b_31304297.jpg)
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=1738927467-cfny1Ho5ZhIWuzXRnbGVDwfDlu08uAYU-0-625091451c549a6c32500f1e18618da4)
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=1738927467-6Gi1uZLlRSV6FRVc7pFXE86X33aRwAcX-0-accd4f72cc3729a242295a60b23d404d)
其中,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=1738927467-wwgIIbFwSznrGt15eFrOnqkdMdrhduVj-0-0ea60135350d8715c4af775c6b0647f3)
3.串删除函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-82.jpg?sign=1738927467-IPfFNAIuPMxm7xndWv0QniFtwhbFM1An-0-b491de1dcc5d65ad54620843a210d840)
4.串复制函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-83.jpg?sign=1738927467-xgtYUm0rf8cCKykTH0gp93aP1fMfhh0A-0-e8ff1d2e7d5b51f48bba4e8c33868ad1)
5.判空函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-84.jpg?sign=1738927467-YJOtWwade3Yulu8iiP4PWgoAcgAGD4ya-0-2e26739de714873be288685521ed35ac)
6.串比较函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-86.jpg?sign=1738927467-BOGuV3VEXUIYmZWhOPjMFaLCqjrvTjrf-0-769bf6f0d115007b1099cac312823ebf)
7.求串长函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-87.jpg?sign=1738927467-fHwxPZOK0zmR9grS14fyEbwrR5G0o0ZL-0-e35c4eaed5a31db2cd9e22a2daaf6dfd)
8.清空串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-88.jpg?sign=1738927467-b93Qjgjjgdpln8ib7d0cse5QilMyKl21-0-e165eb26a6a371af830c7cd8c691d56a)
9.联接串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-89.jpg?sign=1738927467-AycYGdGlb50KfECMIVNAHVq0gYwGVj0E-0-a7d0e783e7b40fbc5fb9f8a929116a60)
10.求子串函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-90.jpg?sign=1738927467-47chlhFSzUp2wdxSuo5C7DRKEbLEsb90-0-3c78748af52869a3dffae5066574342f)
11.定位函数
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-91.jpg?sign=1738927467-AGtWgJGOFlP5XYFR8Vz5gmCUC0N3xz4I-0-6e6be8b2b71aff74b5fcf56bd779d096)
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=1738927467-lWmeMD068RYKDBM7i7XFKNqEGKYkMqnD-0-b41ee50c46dbe72e66ddda25558830c3)
一般形式二维数组
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-93.jpg?sign=1738927467-TxQRPqiiNcySmXwQrVdEmVy12WQ82ZWR-0-729b0395365f692749e48196dd76050a)
数组结构具有3个性质:
●数据元素数目固定,即一旦说明了一个数组结构,其元素数目不再有增减变化。
●数据元素具有相同的类型。
●数据元素的下标关系具有上下界的约束并且下标有序。
对于数组,通常只有以下两种运算:
●给定一组下标,存取相应的数据元素。
●给定一组下标,修改相应数据元素中的某个数据项的值。
2.数组的顺序存储结构
由于计算机的存储单元是一维结构,而数组是多维结构,要用一维的连续单元存放数组的元素,就有存放次序的约定问题。根据不同的存放形式可以分为以下几种类型。
(1)按行优先顺序存放
按行优先顺序存放就是按行切分,如上述二维数组A23,按行切分可得如图3-19所示存放顺序。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-94.jpg?sign=1738927467-P0JOAmEL0pzqrKwWErOGsIQh0JpfMJD2-0-1c94e650329ed3dda55d0bd7fbfc87be)
图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=1738927467-CL3AxDc7olSJeNbifMC8SzOvUA8JBlgk-0-93817f6829f9dcac742e5fa960883e89)
图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=1738927467-Q5xGgFKeA6BqSxO2FjD0Gp3ExVghC4ak-0-7178582d222b45c79a169f77de50b581)
要访问第5个元素,可以采用下面写法:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-97.jpg?sign=1738927467-W4SqIYxMCi2bVIOxE593uiHBKt0Zdv4k-0-23cedadcfa9d8e459ec96f3e853e0369)
二维数组时:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-98.jpg?sign=1738927467-V6tpjcuW8uwZNsOGEBWXWMc51KfZYdp4-0-4d91a03fbc58fb9a38d034c2e0cfae46)
要访问a32=9,则
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-99.jpg?sign=1738927467-Bh0Yh0BTt4VYDG9JtIdddfJlLMeV2eli-0-0b6e3bef0782dcd1a23b4ed0dbdf93e3)
(2)按列优先顺序存放
如果数组按列切分,就得到按列优先顺序存放方式,仍以上述二维数组A23为例,按列切分可得如图3-21所示存放顺序。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-100.jpg?sign=1738927467-eW4NPmv17U4UpLyPFc8v3zb8tseniLhi-0-fe4d8c6033f5421965217f56d0f51aed)
图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=1738927467-vHaYN23EwSMbupe3cmSU9Wbzsx05l5LI-0-506ded2529441c406ca0db9048ea6238)
图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=1738927467-NTy4ovxkfJRmYk4tMfPtwHKKeMceuSzA-0-0c03c530324fd88ad9aa7c4073856d10)
若将其中非零元素按行优先顺序存放,则
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-103.jpg?sign=1738927467-DpP40f1IZ4cnL0MT7XTnEIxqNBHzrtkn-0-9d74b1dfe50dc6bbb59292fa733b2761)
从第1行至第i-1行的非零元素个数为
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-104.jpg?sign=1738927467-MYpgwhwJHNYb3eUubEUEMENrfgdAMfG4-0-318604d4df621510a0140d138d462c8c)
求取其中非零元素aij地址的关系式为:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-105.jpg?sign=1738927467-605ilHnlCvXParjFcRLHYtsxEOsOsLQX-0-00ecea7ad9814131f0862d4451e2acb5)
(2)三对角阵的存储方式
设Ann为三对角阵:
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-106.jpg?sign=1738927467-PltRQG6bGoNM6orOjMM4n5iea2cZZG3r-0-5bad51a4519cbd32848c392f01b78f10)
若将其中非零元素按行优先顺序存放,则
{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=1738927467-RHhPBmxPEZKbPNazrzuYRzRaYUvUOT0l-0-f3d341fa08a62119f581f4d4a8c98151)
类似三对角阵的存储。
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=1738927467-1sduXNfe8HBAGAxE2idDT9cdK1pvlk2j-0-6ff3a298cf73654ae5889d3fe9c17bd1)
稀疏矩阵用三元组表示的例子如图3-23所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-109.jpg?sign=1738927467-mfktVwyv6rPYqBmYG6u5FW6eWHOcKL9V-0-dbc72de918de01bb914845ca349b3ac9)
图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=1738927467-7HM3vAK3mL3CtthyayUj4pjrKIMq9m5e-0-9083e64af85eb1ba986587728efd27f0)
它的执行时间为O(m×n)。由于稀疏矩阵含有大量的零元素,这种方法显然不经济。以下介绍三元组表的转置算法。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-111.jpg?sign=1738927467-q3qjYpWAqxHbv9q7Lo1NSPk36JOz1r32-0-767ab376178edb7414c7818cc93ce26b)
它的执行时间为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=1738927467-WeMv4SaumK9zEkrumhWnsmdO1dUq71KZ-0-3fe86ef223a187b3aee0b1dfc0783e85)
图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=1738927467-mJctdUSMJ0TftE4Own2hLV7vPE6jMLtg-0-ee3564e27258704ec61ca0f5564e5bd8)
图3-25 十字链表结构
例如,对上述矩阵建立十字链表
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-115.jpg?sign=1738927467-5JvGavWfTzUd5HkCSP3aquYT4Jmdjiqm-0-1e198ff6e91f021f0e208c9464b3f362)
建立链表表头,如图3-26所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-116.jpg?sign=1738927467-NTF03KRfhLtVhWcDNaNhSMN4RVlgGXsM-0-0ea25b7f6221c81daf6ccb9263125fd2)
图3-26 十字链表表头
插入非零结点,行、列构成循环链表,如图3-27所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-117.jpg?sign=1738927467-391jhshV0TOrU4L9tfZUYfF7Zay0qMNu-0-ce3bc8ddcece843164c286b2b8327e89)
图3-27 插入非零结点后的十字链表
增加附加头结点,头结点中row、col分别存放稀疏矩阵的行数和列数,并将所有表头构成循环链表,如图3-28所示。
![](https://epubservercos.yuewen.com/70D625/16948915704920906/epubprivate/OEBPS/Images/978-7-111-50308-8-Chapter03-118.jpg?sign=1738927467-pO09A4Sc3c3KBReVe0mrEJZmvC4GnK9V-0-5cdfd9f97042c465af94c728e0f542e6)
图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=1738927467-GwkL8VX3mxqjHgwiBKm0JuBmZqYeWFyo-0-1060a38f544736f3d943fbd66e84cff9)
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=1738927467-N03XobwqrrZJsXYKoWAc0Ta8nHafosjl-0-93c10143b73cd1ccc4ef66b45233259d)
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=1738927467-uOnhynr0DDDrTeIDXfb7LrFtVkE1Js9h-0-ce19c72b8cf0764e5281c98972560e4f)