考研数据结构笔记--数组、矩阵和广义表

一、数组

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 稀疏矩阵

常用的稀疏矩阵顺序存储方法有三元组表示法和伪地址表示法。

  1. 三元组表示法
//结构体定义如下
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];
  1. 伪地址表示法

​ 伪地址即元素在矩阵中按照行优先或者列优先存储的相对位置,用伪地址方法存储洗漱矩阵和三元组方法相似,只是三元组每一行中有两个存储单元存放地址,而只用另一个来存放伪地址。这种方法需要2N个存储单元,N为非零元素个数。元素A[i][j]的伪地址计算方法为n(i-1)+j

常用的稀疏矩阵链式存储方法有邻接表法和十字链表表示法。

  1. 邻接表表示法

​ 邻接表表示法将矩阵中每一行的非零元素串连成一个链表,链表结点中有两个分量,分别表示该结点对应的元素值及其列号。

  1. 十字链表表示法

​ 在稀疏矩阵的十字链表存储结构中,矩阵的每一行都用一个带头结点的链表标志,每一列也用一个带头结点的链表表示,这种存储存储结构中的链表结点都有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;
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值