当前位置:网站首页>线性表的基本概念
线性表的基本概念
2022-07-31 11:53:00 【马可爱家的马可爱】
1、线性表的相关基本概念
前驱:当前节点的前一个节点
后继:当前节点的后一个节点
表长: 线性表的长度是线性表中元素的个数,随着线性表的插入和删除操作的进行,这个量是变化的
空表:线性表中的个数n定义为线性表的长度,n=0时称为空表
首元结点:链表中存储线性表中第一个数据元素a1的结点。为了操作方便,通常在链表的首元结点之前附设一个结点
头结点:头结点一般用于标志线性表的开始,数据域中可以存放数据或不存放数据,存放数据的头结点相当于整个线性表不带头结点(即将头结点看作一个普通的结点,头结点是链表的非必要元素)
头指针:确定线性表中第一个元素对应的存储位置,头指针是链表的必要元素(单链表是由头指针唯一确定的)
2、线性表的结构特点
除第一及最后一个元素外,每个结点都只有一个前趋和只有一个后继。
3、静态链表和顺序表的相似以及不同之处
静态链表结构类型的描述
#define MaxSize 100 //定义静态链表最大长度
typedef struct{
//静态链表结构类型的定义
ElemType data; //数据域
int next; //类指针域, 下一个元素的数据下标,类似于动态链表中的next指针域
}SLinkList[MaxSize];
顺序表结构类型的描述
静态分配:存储空间固定的分配,数组大小和空间
#define MaxSize 50 //定义线性表的最大长度
typedef struct{
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
动态分配:存储空间在程序执行时动态分配存储空间
#define InitSize 100 //表长度的初始长度
typedef struct{
ElemType *data; //动态分配数组的指针
int MaxSize, length; //数组的最大容量和当前个数
}SeqList; //动态分配数组顺序表的类型定义
注意 : 静态分配一旦空间占满后面再加入的数据会溢出;动态分配的空间一旦被占满,会先开辟一块比原来更大的空间用来存放原来的数据和新数据,再释放原来已满的空间,而不是直接在原来的空间上拓展新空间。因为顺序存储分配的存储空间都是连续的。
顺序表和静态链表的物理结构(即存储结构)是相同的,在计算机内存中以数组的形式保存的线性表,是用一组地址连续的存储单元依次存储数据元素的线性结构。
但是静态链表不仅具有顺序表根据下标实现随机存取的特性,还有动态链表的特性,增加或删除一个元素,不需要移动任何数据!而顺序表增加或者删除一个元素,需要移动大量的元素!
4、静态链表和动态链表的相似以及不同之处
上面说到静态链表集合了顺序表和动态链表的双重特性,同时具有增删元素不需要移动任何数据和随机存取的特性。所以相比较静态链表,动态链表没有随机存取的特性,要想找到某一元素,必须从头到尾扫描动态链表
5、线性表的链式存储方式及以下几种常用链表的特点和运算
单链表
单链表:
没有随机存取的特性,只能从头开始遍历,顺序存取
增删元素无需移动任何元素,只需修改指针指向即可
判空:
具有头结点:L->next == NULL; (L是头指针)
没有头结点:L == NULL;
单链表是由头指针唯一确定的,确定线性表中第一个元素对应的存储位置,所以头指针是链表的必要元素
//-------------------单链表的存储结构-------------------
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode, *LinkList; //定义单链表结点
循环单链表
循环单链表:
循环单链表是另一种形式的链式存储结构,其特点是表中最后一个节点的指针域指向指向头节点,整个链表形成一个环。由此可以从表中任何一个节点出发均可以找到表中其他节点
判空:
L->next = L;
循环单链表中设置设置尾指针而不设头指针,可以使一些操作简化!如将两个线性表合并成一个线性表的时候,仅需要将第一个表的尾指针指向第二个表的第一个节点,第二个表的尾指针指向第一个表的头结点,然后释放第二个表的头结点即可!
//-------------------循环单链表的存储结构-------------------
typedef struct LNode{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode, *LinkList; //定义单链表结点
双向链表
双向链表:
由于单链表的链式存储结构的节点中只有一个指示直接后继的指针域,由此,从某个节点出发出发只能顺指针向后寻查其他节点。若要寻查节点的直接前驱节点,则必须从表头指针出发,。换句话说,在单链表中,查询直接后继节点的执行时间为O(1),但是查找直接前驱的执行时间为O(n)。所以为了克服单链表这种单向性的缺点,可以利用双向链表
判空:
L ->next = NULL;
//-------------------双向链表的存储结构-------------------
typedef struct DuLNode{
ElemType data; //数据域
struct DuLNode *prior; //指向直接前驱
struct DuLNode *next; //指向直接后驱
}DuLNode, *DuLinkList; //定义双向链表节点
//-------------------初始化双向链表*-----------------------
ElemType InitDuList(DuLinkList&L)
{
L = new DuLNode; //头指针指向头结点
if (L == NULL) //判空条件
{
return ERROR;
}
L->next = NULL; //头节点之后暂时还没有节点
L->prior = NULL; //前指针域指向自己,头节点的prior指针永远为空
return OK;
}
循环双向链表
双向循环链表:
在双链表的基础上,将头结点的prior指针指向最后一个结点, 将最后一个结点的next指针指向头结点,这样就形成一个环
判空:
L -> next = NULL;
//-------------------循环双向链表的存储结构-------------------
typedef struct DuLNode{
ElemType data; //数据域
struct DuLNode *prior; //指向直接前驱
struct DuLNode *next; //指向直接后驱
}DuLNode, *DuLinkList; //定义双向链表节点
//-------------------初始化双向循环链表*-----------------------
ElemType InitDuList(DuLinkList&L)
{
L = new DuLNode; //头指针指向头结点
if (L == NULL) //判空条件
{
return ERROR;
}
L->next = L; //后指针域指向自己,头节点的next指向头节点
L->prior = L; //前指针域指向自己,头节点的prior指向头节点
return OK;
}
循环双向链表中不需要设置尾指针, 因为可以通过头结点去直接访问最后一个结点。
6、线性表的顺序存储及链式存储情况下,其不同的优缺点比较,即其各自适用的场合
(1)、空间上
顺序比链式节约空间。是因为链式结构每一个节点都有一个指针存储域
(2)、存储操作上
顺序支持随机存取,方便操作。而链式需要从头到尾扫描链表才可以完成访问操作!
(3)、插入和删除上
顺序插入或者删除需要移动近乎一半的元素,而链式只需要修改指针指向即可完成操作,无需移动任何元素!
(4)、所以顺序表适用于长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表;而对于频繁进行插入或者删除操作的线性表,可以采用链表作为存储结构!
7、索引存储结构
索引存储:除建立存储结点信息外,还建立附加的索引表来标识结点的地址。索引表由若干索引项组成。
特点:
索引存储结构是用结点的索引号来确定结点存储地址,其优点是检索速度快,缺点是增加了附加的索引表,会占用较多的存储空间。
边栏推荐
- MySQL 的 limit 分页查询及性能问题
- SAP Commerce Cloud Product Review 的添加逻辑
- 502 bad gateway原因、解决方法
- 学习笔记 Golang 写入文件(io.WriteString、ioutil.WriteFile、file.Write、write.WriteString)
- vb.net 画曲线
- strings包详细文档+示例
- 5 个开源的 Rust Web 开发框架,你选择哪个?
- ApiPost is really fragrant and powerful, it's time to throw away Postman and Swagger
- 分布式id解决方案
- 在 Excel 里使用 ODBC 读取 SAP BTP 平台上 CDS view 的数据
猜你喜欢
A Week of Wonderful Content Sharing (Issue 14)
MySql模糊查询大全
想吃菌子,当然是自己上山找了
MySQL百万数据优化总结 一
Obsidian设置图床
Different lower_case_table_names settings for server ('1') and data dictionary ('0') solution
给你一个大厂面试的机会,你能面试上吗?进来看看!
ESP8266-Arduino编程实例-HDC1008温度湿度传感器驱动
The latest MySql installation teaching, very detailed
“带薪划水”偷刷阿里老哥的面经宝典,三次挑战字节,终成正果
随机推荐
数据持久化技术——MP
Service discovery of kubernetes
关于Mysql数据库的介绍
If the value of the enum map does not exist, deserialization is not performed
多线程学习笔记-2.final关键字和不变性
透过开发抽奖小程序,体会创新与迭代
busybox之reboot命令流程分析
JVS设置不同应用的登录时效时间
Data Lake (19): SQL API reads Kafka data and writes it to Iceberg table in real time
Use jOOQ to write vendor-agnostic SQL with JPA's native query or @Formula.
LeetCode - 025. 链表中的两数相加
普林斯顿微积分读本03第二章--编程实现函数图像绘制、三角学回顾
Qt鼠标穿透
Distributed Transactions - Introduction to Distributed Transactions, Distributed Transaction Framework Seata (AT Mode, Tcc Mode, Tcc Vs AT), Distributed Transactions - MQ
基于C51实现按键控制
musl Reference Manual
Redis学习笔记-3.慢查询和其他高级数据结构
蓝牙协议栈开发板 STM32F1 跑蓝牙协议栈 –传统蓝牙搜索演示以及实现原理[通俗易懂]
ESP8266-Arduino编程实例-PIR(被动红外)传感器驱动
若枚举映射的值不存在,则不进行反序列化