线性表的链式表现和实现

线性表的链式表示和实现

【链式存储结构】

结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻

线性表的链式表示又称为非顺序映像或链式映像

用一组物理单位任意的存储单元来存放线性表的数据元素。

这组存储单元既可以是连续的,也可以是不连续的,甚至是零散分布在内存中的任意位置上的。

链表元素的逻辑次序和物理次序不一定相同

单链表:指针域和数据域

头指针:记录第一个元素地址

单链表是由头指针唯一确定,因此单链表可以用头指针的名字来命名。

结点:数据元素的存储映像,由数据域和指针域两部分组成。

链表:n个节点由指针链组成一个链表它是线性表的链式存储映像,称为线性表的链式存储结构

链表分类:单链表、双向链表、循环链表

结点只有一个指针域的链表,称为单链表或线性链表

结点由两个指针域的链表,称为双链表

首位相接的链表称为循环链表(尾结点的后继指针域存放头节点或者首元结点的地址)

头指针:是指向链表中第一个结点的指针

首元结点:是指链表中存储第一个数据元素a1的结点

头节点:是在链表的首元结点之前附设的一个结点

【不带头结点】

头指针直接指向首元结点

【带头结点】

头指针指向头节点,头指针指针域存储首元结点地址

如何表示空表

无头结点时,头指针为空时表示空表用 ^表示

有头结点时,当头节点的指针域为空时表示空表

为什么加头节点

【1】便于处理首元结点的处理

首元结点的地址保存在头节点的指针域中,所以链表的第一个位置上的操作和其他位置一致,无须进行特殊处理.

【2】便于空表和非空表的统一处理

无论链表是否为空,头指针都是指向头节点的非空指针,因此空表和非空表的处理也就统一了。

头节点的数据域内装的是什么?

头节点的数据域可以为空,也可以放线性表长度等附加信息,但此节点不能计入链表长度值

链表的特点:

(1)结点在存储器中位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻

(2)访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等。

链表-》顺序存取(必须从头开始一个一个找)

【带头结点单链表】

单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名,若头指针名是l,则称链表为表l

单链表初始化:
生成新结点做头结点,用头指针L指向头结点。

将头结点的指针域置空

判断链表是否为空(链表种无元素,称为空链表(头指针和头结点仍存在))

【思路】判断头结点指针域是否为空

单链表的销毁:链表销毁后不存在

【思路】从头指针开始,依次释放所有结点

清空链表

链表任然存在,但链表中无元素,成为空链表(头指针和头结点仍然在)

【算法思路】依次释放所有结点,并将头结点指针域设置为空

求单链表表长

【思路】从首元结点,依次计数所有结点

取值:取单链表种第i个元素的内容

从链表的头指针出发,顺着链域next逐个结点往下搜索,直至搜索到第i个结点为止。因此,链表不是随机存储结构

查找:按值查找:根据指定数据获取数据所在位置(地址)O(n)

按值查找:根据指定数据获取数据所在的位置序号

插入:在第i个结点前插入新节点O(1)

先创建一个结点,插入数据写在里面数据域,(先)创建结点后继指向第i个结点,(后)插入位置结点前结点后继指向创建结点。

先后顺序不能变,会丢失原来结点地址

如果要换需要借助其他结点

image-20220319213819594

删除:删除第i个结点O(1)(只修改指针)

如果要在单链表中进行前插或删除操作,由于要从查找前驱结点,所耗时间复杂度O(n)

【思路】找到元素,如果删除元素有用保存

将删除元素都节点地址给删除元素前结点

p->next=p->next->next

单链表的建立:

头插法:(元素插入链表头部)O(n)

尾插法:O(n)

从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点

初始时,r同L均指向头结点。每读入一个数据元素则申请一个新节点,将新节点插入到尾结点后,r指向新结点

循环链表

尾结点指针域指向头结点

优点:从表种任一结点出发都可以找到表中其他结点

双向链表

为什么要讨论双向链表

单链表的结点->y有指示后继的指针域->找后继结点方便;

即:查找某结点的后继结点的执行时间为O(1)

无指示前驱的指针域->找前驱结点难:从表头出发查找

即:查找某结点的前驱结点的执行时间为O(n)

【解决方法】可以用双向链表来克服单链表的这种缺点

双向链表:在单链表的每个结点再增加一个指向其直接前驱的指针域prior,这样链表中就形成了由两个方向不同的链,故称为双向链表

双向链表定义三个成员(两个指针域,一个数据域 )

空表情况下头结点两个指针域都为空

头指针的前驱指针域为空,最后一个结点后继为空

双向循环链表

和单链表的循环类似,双向链表也可以有循环表

让头结点的前驱指针指向链表的最后一个结点

让最后一个结点的后继指针指向头结点

双向链表结构的对称性

p->prior->next=p=p->next->prior

在双向链表中有些操作(如:ListLength、GetElem等),因仅涉及一个方向的指针,故它们的算法与线性链表的相同。但在插入、删除时。则需要同时修改两个方向上的指针,两者的操作的时间复杂度均为O(n)

双向链表的插入

image-20220320202206412

顺序表和链表的比较

链式存储结构的优点:
结点空间可以动态申请和释放

数据元素的逻辑次序靠结点的指针来指示,插入和删除时不需要移动数据元素

链式存储结构的缺点

存储密度小,每个结点的指针域需额外占用存储空间。当每个结点的数据域所占字节不多时,指针域所占存储空间的比重显得很大

存储密度=结点数据本身占用空间/结点占用的空间总量

一般,存储密度越大,存储空间的利用率就越高。显然,顺序表的存储密度为1(100%),而链表的存储密度小于1

链式存储结构式分随机存取的结构。对任一节点的操作都要从头指针依指针链查找到该结点,这增加了算法的的复杂度

image-20220320203242908

线性表的应用

线性表的合并

问题描述:

​ 假设利用两个线性表La和Lb分别表示两个集合A和B,现要求一个新的集合A=A交B

La=(7,5,3,11) Lb=(2,6,3)---->La=(7,5,3,11,2,6)

有序表的合并

问题描述:

已知线性表La和Lb中的元素按值非递减有序排列,现要求将La,Lb归并为一个新的线性表Lc,且Lc中的数据元素仍按值非递减有序排列

La=(1,7,8) Lb=(2,4,6,8,10,11)-->Lc=(1,2,4,6,7,8,8,10,11)

posted @   我是一个大废物  阅读(259)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示