第四章串、数组、广义表(4.4-4.5)
4.4数组
4.4.1数组的类型定义
1.数组的定义
n维数组中含有 ∏ i = 1 n b i \prod _ {i = 1} ^ n b_i ∏i=1nbi个数据元素,每个数据元素都受着n个关系的约束
在每个关系中,元素 a j 1 j 2 ⋯ j n ( 0 ≤ j i ≤ b i − 2 ) a _ {j _ 1 j _ 2 \cdots j _ n}(0 \le j _ i \le b _ i - 2) aj1j2⋯jn(0≤ji≤bi−2)都有一个直接后继元素。
因此,就其单个关系而言,这n个关系仍是线性关系。
与线性表一样,所有数据元素都必须属于同一数据类型。
数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作
2.抽象数据类型数组的定义:
ADT Array{
数据对象: ji=O, ···,bi-1, i=l, 2, …, n,
D = { a ·ln(>O)称为数组的维数,bi是数组第i 维的长度,ji是数组元素的第j维下标,aJ1边'"Jn
数据关系: R = {Rl,R2, …, Rn}
基本操作:
InitArray (&A, n, bound i, ···, boundn)
操作结果:若维数n和各维长度合法, 则构造相应的数组A, 并返回OK。
DestroyArray (&A)
操作结果:销毁数组A。
Value(A,&e, indexl , …,indexn)
初始条件:A是n维数组,e为元素变量,随后是n个下标值。
操作结果:若各下标不超界,则e赋值为所指定的 A 的元素值, 并返回OK。
Assign(&A,e, indexl, …,indexn)
初始条件:A是 n 维数组, e 为元素变扯,随后是 n 个下标值。
操作结果:若下标不超界,则将 e 的值赋给所指定的A的元素, 并返回OK。
} ADT Array
4.4.2数组的顺序存储
数组元素的存储位置是其下标的线性函数,一旦确定了数组各维的长度,Ci就是常数。由千计算各 个元素存储位置的时间相等,所以存取数组中任一元素的时间也相等,即数组是一种随机存取结构。
二维数组的两种存储方式:行优先、列优先。
4.4.3特殊矩阵的压缩存储
假若值相同的元素或者零元素在矩阵中的分布有一定规律, 则称此类矩阵为特殊矩阵。
特殊矩阵主要包括对称矩阵、 三角矩阵和对角矩阵等, 下面我们重点讨论这三种特殊矩阵的压缩存储。
1.对称矩阵
1.1特点:
若 n 阶矩阵A中的元满足下述性质:aij=aji (1≤i,j≤n)
1.2存储:
对于对称矩阵,可以为每一对对称元分配一个存储空间,则可将忙个元压缩存储到 n(n + 1)/2 个元的空间中, 不失一般性, 可以行序为
主序存储其下三角 (包括对角线)中的元。
1.3规律:
求位置aji的位置k,满足以下规律:
2.三角矩阵
2.1特点:
对角线以下(或者以上)的数据元素(不包括对角线)全部为常数c。
2.2存储:
重复元素c共享一个元素存储空间,共占用n(n+1)/2+1个元素空间.
2.3规律:
①上三角矩阵(行优先存储)中求位置aji的位置k,满足以下规律:
②下三角矩阵(行优先存储)中求位置aji的位置k,满足以下规律:
3.对角矩阵
3.1特点:
在n´n的方阵中,非零元素集中在主对角线及其两侧共L(奇数)条对角线的带状区域内 — L对角矩阵。

3.2存储:
以对角线的顺序存储。
3.3规律:
求位置aji的位置k,满足以下规律:k=(i1+2)n+j1=(i-j+2)n+j
4.5广义表
4.5.1广义表的定义
顾名思义,广义表是线性表的推广,也称为列表。广泛地用千人工智能等领域的表处理语言。LISP语言,把广义表作为基本的数据结构,就连程序也表示为一系列的广义表。
记作LS = (a0, a1, a2, …, an-1)。
其中,LS是广义表(a1, a2, …,an )的名称,n是其长度。在线性表的定义中,ai(1≤i≤n)只限千是单个元素。而在广义表的定义中,a; 可以是单个元素,也可以是广义表,分别称为广义表 LS的原子和子表。习惯上,用大写字母表示广义表的名称,用小写字母表示原子。
①线性表的元素都是结构上不可分的单元素;
②广义表的元素可以是单元素,也可以是有结构的表;
③广义表不一定是线性表。
4.5.2广义表的存储结构
1.头尾链表的存储结构
由千广义表中的数据元素可能为原子或广义表,由此需要两种结构的结点:一种是表结点, 用以表示广义表; 一种是原子结点, 用以表示原子。从上节得知:若广义表不空, 则可分解成表头和表尾, 因此, 一对确定的表头和表尾可唯一确定广义表。 一个表结点可由3个域组成:标志域、 指示表头 的指针域和指示表尾的指针域。而原子结点只需两个域 :标志域和值域。如图4.15所示, 其中tag是标志域 , 值为1时表明结点是子表, 值为0时表明结点是原子。
typedef enum
{
ATOM, // 0,表示原子
LIST // 1,表示子表
}ElemTag;
typedef struct GLNode
{
ElemTag tag; //公共部分,用于区分原子节点和表结点
union //根据 tag 二选一
{ //要么是原子节点的值域,要么是表结点的头尾节点指针域
AtomType atom;
struct { struct GLNode *hp, *tp } ptr;
};
} *GList //广义表类型
2.扩展线性链表的存储结构
typedef enum
{
ATOM, // 0,表示原子
LIST // 1,表示列表
} ElemTag;
typedef struct GLNode
{
ElemType tag; // 公共部分,用于区分原子结点和表结点
union
{
AtomType atom; // 原子结点的值域
struct GLNode *hp; // 表结点的表头指针
};
struct GLNode *tp; //相当于与线性链表的next,指向下一个结点
} *GList;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY