重学《数据结构与算法》!记录一下,方便遗忘!主要学习视频是B站王卓老师的课程!
0 引言
线性结构的定义:若结构是非空有限集,则有且仅有一个开始结点和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。
可表示为:(a1 , a2 , ……, an)
线性结构包括线性表、堆/栈、队列、字符串、数组、广义表等等,其中,最典型、最常用的就是线性表。
那既然是线性结构,顾名思义,其各个数据元素之间是线性关系的。
1 线性表的定义和特点
定义:线性表是具有相同特性的数据元素的一个有限序列。
特点:各个数据元素之间是线性关系。
在非空的线性表中,有且仅有一个开始结点
,它没有直接前趋,而仅有一个直接后继
。
有且仅有一个终端结点
,它没有直接后继,而仅有一个直接前趋
。
其余内部结点
都有且仅有一个直接前趋
和一个直接后继
。
2 线性表的顺序表示和实现(顺序表)
线性表按其在计算机内的存储结构不同,分为顺序表(顺序存储结构)和链表(链式存储结构)。
顺序存储结构:逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。
也就是说,线性表的顺序存储结构占用一片连续的存储空间。
因此我们可以方便地计算顺序表中元素的存储位置(不码了,直接用图代替吧)。
例如:假设每个元素占用8个存储单元,
存储位置是2000单元,则
存储位置就是2008单元,
存储位置就是1992单元。
综上,总结顺序表的特点:以物理位置相邻表示逻辑关系。任一元素均可随机存取。
看到这里,也许你会想,“咦,和数组好像啊。。。”
是的,顺序表元素和数组元素都具有以下特点:地址连续、依次存放、随机存取、类型相同。因此,我们可以用一维数组来表示顺序表。
那它们不同点在哪里呢?那就是数组长度不可变(在声明时就确定了其长度,这个长度在程序运行期间是固定的,不能动态增加或减少),是静态的;线性表长度可变(即可以动态增/删元素)。基于此,我们还需要使用一个变量来跟踪顺序表的当前长度(这个变量不存储元素本身,而是记录顺序表中元素的数量,以便进行动态的增删操作。)。
【顺序表的存储结构定义】
# define MAXSIZE 100 //定义线性表存储空间的最大长度 typedef struct { ElemType *elem; //指向数据元素的基地址 int length; //线性表的当前长度 }SqList;
说明:1. 数组空间要等顺序表初始化动态分配得到,初始化完成后,数组指针elem指示顺序表的基地址,数组空间大小为MAXSIZE;
2. 元素类型定义中的ElemType数据类型是为了描述统一而自定的,它可以是基本数据类型如int、float、char等,或是构造数据类型如struct结构体类型。
当然,顺序表的存储结构也可以用另一种定义方式:
typedef struct { ElemType *elem; // 存储空间基址 int length; // 当前长度,实际存储的元素个数 int listsize; // 当前分配的存储容量,即最多可以存储的元素个数,类似于MAXSIZE } SqList;
例如,图书表的顺序存储结构类型定义:
#define MAXSIZE 10000 //图书表可能达到的最大长度
typedef struct //图书信息定义
{
char no[20]; //图书编号
char name[50]; //图书名字
float price; //图书价格
}Book;
typedef struct
{
Book *elem; //存储空间的基地址
int length; //图书表中当前图书个数
}SqList; //图书表的顺序存储结构类型为SqList
下面重点来了