概述
数组、矩阵和广义表
- 一、数组
- 1.1考研中常用的两种数组:
- 1.2 二维数组的两种存储方式
- 二、矩阵的压缩存储
- 2.1 对称矩阵
- 2.2 三角矩阵
- 2.3 对角矩阵
- 2.4 稀疏矩阵
- 三、广义表
- 3.1 概念
- 3.2 三个重要结论
- 3.3 广义表的存储结构
一、数组
1.1考研中常用的两种数组:
-
一维数组
(a0, a1, a2, ……, an-1)
-
二维数组
[(a0, 0, a0, 1, a0, 2, ……, a0, n-1),
(a1, 0, a1, 1, a1, 2, ……, a1,n-1),
…,
(an-1, 0, an-1, 1, an-1, 2, ……, an-1, n-1)]
数组一般采用顺序存储的方式,数组一旦被定义,它的维数和维界就不再改变。
1.2 二维数组的两种存储方式
以列序为主的存储结构和以行序为主的存储结构。
以以行序为主的存储结构为例:
假设每个数据元素占L个存储单元,则二维数组A中任一元素aij的存储位置可以由下式确定
LOC(i, j) = LOC(0, 0) + (b2 * i + j) * L
其中LOC(i, j)表示aij的存储位置,LOC(0, 0)是二维数组A的起始存储位置,也称为基址,b2表示数组第2维的长度。
C语言是以行序为主的存储结构
二、矩阵的压缩存储
当矩阵中许多值相同的元素或者是零元素时,为了节约存储空间,可以对这类矩阵进行压缩存储。如果值相同的元素或者零元素在矩阵中的分布有一定的规律,那么我们称这类矩阵为特殊矩阵,反之称为稀疏矩阵。
特殊矩阵最常见的有三种:对称矩阵,三角矩阵和对角矩阵。
2.1 对称矩阵
矩阵中的元素满足ai,j = aj, i ,的矩阵称为对称矩阵,对于对称矩阵的存储,我们可以为每一对对称元分配一个存储空间,则可将n2个元压缩存储到n(n+1)/2个元的空间中。
2.2 三角矩阵
三角矩阵分为上三角矩阵和下三角矩阵,三角矩阵的存储方式和对称矩阵的存储方式类似,以下三角矩阵为例,我们只需要存储对角线及其下部分的元素和其上三角中的一个元素C即可。
2.3 对角矩阵
除主对角线以及其上下两个条带状区域内的元素外,其余元素都为C。我们可以以行为主或者以对角线的顺序将其压缩到一维数组中。
2.4 稀疏矩阵
常用的稀疏矩阵顺序存储方法有三元组表示法和伪地址表示法。
- 三元组表示法
//结构体定义如下
typedef struct{
int val;//值
int i, j; //i行下标,j列下标
}Triple;
typedef struct{
Triple data[MAXSIZE + 1]; //非零元三元组表
int mu, nu, tu;
//矩阵的行数、列数和非零元素个数
}TSMatrix;
//如果要定义一个含有maxterms个非零元素的稀疏矩阵,可按如下方式定义
Triple trimat[maxterms+1];
//为了简单表示这个三元组,我们可以直接定义成一个二维数组
int trimat[maxterms+1][3];
- 伪地址表示法
伪地址即元素在矩阵中按照行优先或者列优先存储的相对位置,用伪地址方法存储洗漱矩阵和三元组方法相似,只是三元组每一行中有两个存储单元存放地址,而只用另一个来存放伪地址。这种方法需要2N个存储单元,N为非零元素个数。元素A[i][j]的伪地址计算方法为n(i-1)+j
。
常用的稀疏矩阵链式存储方法有邻接表法和十字链表表示法。
- 邻接表表示法
邻接表表示法将矩阵中每一行的非零元素串连成一个链表,链表结点中有两个分量,分别表示该结点对应的元素值及其列号。
- 十字链表表示法
在稀疏矩阵的十字链表存储结构中,矩阵的每一行都用一个带头结点的链表标志,每一列也用一个带头结点的链表表示,这种存储存储结构中的链表结点都有5个分量:行分量、列分量、数据域分量、指向下方结点的指针、指向右方结点的指针。
//十字链表的结构体定义
//普通结点结构定义
typedef struct OLNode{
int row, col;
//行号和列号
struct OLNode *right, *down; //指向右边结点和下方结点的指针
float val;
//数据域
}OLNode;
//头结点结构体定义
typedef struct{
OLNode *rhead, *chead; //指向两头结点数组的指针
int m, n, k;
//矩阵行数、列数以及非零结点总数
}CrossList;
三、广义表
3.1 概念
广义表:是线性表的推广,表中元素可以是原子或者广义表。有人称其为列表(List);
广义表的长度:表中最上层元素的个数;
广义表的深度:表中括号的最大层数,求广义表深度时需要将子表展开。
表头和表尾:当广义表***非空时***,第一个元素为广义表的表头,其余元素组成的表是广义表的表尾。
Examples:
A=(), 空表,长度为0,深度为1
B=(d, e), B的元素全是原子,长度为2,深度为1
C=(b, (c, d)), C中元素一个原子和一个广义表,长度为2,深度为2
D=(B, C), D中元素为两个已经定义好的广义表,长度为2,深度为3
E=(a, E), E有两个元素,分别是原子a和它本身,长度为2,深度度为无限深
F=(a, (c, d, (e, f)), (g, k))
F的表头为a,表尾为((c, d, (e, f)), (g, k))
G=((a, b), (g, k))
G的表头为(a, b), 表尾为((g, k))
A的表头为 空,表尾为空表
3.2 三个重要结论
(1) 列表的元素可以是子表,而表的元素还可以是子表……由此,列表是一个多层次的结构,可以用图形象的表示。
(2) 列表可为其它列表所共享。就像Example中的广义表D一样,直接通过子表的名称来引用
(3) 列表可以是一个递归表,即列表也可以是其本身的一个子表,如Examples中的广义表E。
3.3 广义表的存储结构
//广义表的头尾链表存储表示
//由此需要两种结构的结点:一种是表结点,用以表示列表;一种是原子结点,用以表示原子
//一个表结点由标志域、指示表头的指针域和指示表尾的指针域组成
//一个原子结点由标志域和值域组成
typedef enum {ATOM, LIST} ElemTag; //ATOM == 0:原子, LIST==1:子表
typedef struct GLNode{
ElemTag tag;
union {
AtomType atom;
struct {
struct GLNode *hp, *tp;
}ptr;
};
}*GList;
//广义表的扩展线性链表存储表示
typedef enum {ATOM, LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
AtomType atom;
struct GLNode *hp;
};
struct GLNode *tp; //相当于线性链表的next,指向下一个元素结点
}*GList;
最后
以上就是感动往事为你收集整理的考研数据结构笔记--数组、矩阵和广义表的全部内容,希望文章能够帮你解决考研数据结构笔记--数组、矩阵和广义表所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复