【链表——数据结构】

文章目录

1.单链表

1.定义

用链式存储"(存储结构实现了 "线性结构" (逻辑结构))

一个结点存储-个数据元素

各结点间的先后关系用一个指针表示
单链表:表尾结点的next指针指向NULL
单链表:从一个结点出发只能找到后续的各个结点

两种实现

1.不带头结点

空表判断: L= =NULL。写代码不方便

2.带头结点

空表判断:L-> next= =NULL。写代码更方便

2.基本操作

1.带头结点

头结点可以看作"第0个"结点

找到第i-1个结点,将新结点插入其后

2.1.不带头结点

不存在"第0个" 结点,因此i=1时需要特殊处理

找到第i-1个结点,将新结点插入其后

如果不带头结点,则插入、删除第1个元素时,需要更改头指针L

2.2后插
2.3前插



2.4删除

头结点可以看作"第0个"结点

找到第i-1个结点,将其指针指向第i+ 1个结点,并释放第i个结点

时间复杂度O(n)

有坑:指定结点是最后一-个结点时,需要特殊处理

2.5按位查找

单链表不具备"随机访问"的特性,只能依次扫描

平均查找长度O(n)

2.6按值查找

平均查找长度O(n)

2.7求单链表长度

时间复杂度O(n)

2.8 建表

1.尾插法

初始化单链表

设置变量length记录链表长度

While循环{
每次取一个数据元素e;
ListInsert (L, length+ 1, e)插到尾部;
length+ +;
}

2.头插法

头插法建立单链表: .

初始化单链表

While循环{
每次取一个数据元素e;
InsertNextNode (L, e);
}

2.双链表

1.初始化

头结点的prior,next都指向NULL

2.插入(后插)

注意新插入结点、前驱节点、后继结点的指针修改

边界情况:新插入结点在最后一个位置,需特殊处理

3.删除(后删)

注意删除结点的前驱结点、后继结点的指针修改

边界情况:如果被删除结点是最后-个数据结点,需特殊处理

4.遍历

从一个给定结点开始,后向遍历、前向遍历的实现(循环终止条件)

链表不具备随机存取特性,查找操作只能通过顺序遍历实现

3.循环链表

1.循环单链表

空表

非空表

2.循环双链表

空表

非空表

3.代码问题

判空

如何判断结点p是否表尾/表头结点

如何在表头、表中、表尾插入/删除一个结点

4.静态链表

用数组的方式实现的链表

分配一整片连续的内存空间,各个结点集中安置

每个数据元素4B,每个游标4B (每个结点共8B)设起始地址为addr

如何定义一个静态链表

1.简述基本操作的实现
1.初始化

把a[0]的next设为-1

把其他结点的next设为一个特殊值用来表示结点空闲

查找从头 结点出发挨个往后遍历结点

####2.插入位序为i的结点

①找到一个空的结点,存入数据元素

②从头结点出发找到位序为i-1的结点

③修改新结点的next

④修改i-1号结点的next

3.删除某个结点

①从头结点出发找到前驱结点

②修改前驱结点的游

③被删除结点next设为-2 .

4.优缺点

优点:增、删操作不需要大量移动元素

缺点:不能随机存取,只能从头结点开始依次往后查找;容量固定不可变

5.适用场景

①不支持指针的低级语言.

②数据元素数量固定不变的场景(如操作系统的文件分配表FAT)

5.线性表

值得注意的特性

数据元素同类型、有限、有序

重要的术语

n为表长、当n=0时为空表

表头a、 表尾a------注意: 位序从1开始数组下标从0开始

前驱、后继------除第- -个元素外,每个元素有且仅有一一个直接前驱;除最后-个元素外,每个元素有且仅有一个直接后继

数据元素的位序a; (从1开始)

**"逻辑结构"**一a1 →a2→a3→a4→a5

基本操作

1.从无到有,从有到无

InitList(&L):初始化表。构造-个空的线性表L, 分配内存空间。

DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间。

2.增 删(改)

ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e.

ListDelete(&L,i,&e):删除操作。删除表l中第i个位置的元素,并用e返回删除元素的值。

3.("改"之前也要"查" )

LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素

GetElem(Li):按位查找操作。获取表L中第i个位置的元素的值。

4.判空、判长、打印输出(还可以自己根据实际需求增加其它基本操作)

Length(L):求表长。返回线性表L的长度,即L中数据元素的个数。

PrintList(L):输出操作。按前后顺序输出线性表l的所有元素值。

Empty(L):判空操作。若L为空表,则返回true,否则返回false.

6.顺序表

定义(如何用代码实现)

存储结构一逻辑 上相邻的数据元素物理上也相邻

使用"静态数组"实现

实现方式

1.静态分配

给各个数据元素分配连续的存储空间,大小为

大小一旦确定就无法改变

2.动态分配

使用"动态数组"实现

L.data= (Elemtype *) malloc (sizeof(ElemType)*size);

顺序表存满时,可再用malloc动态拓展顺序表的最大容量

需要将数据元素复制到新的存储区域,并用free函数释放原区域

缺点:时间开销大

3. 特点

①随机访问,即可以在0(1)时间内找到第i个元素。

②存储密度高, 每个节点只存储数据元素

③拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比

较高)

④插入、删除操作不方便,需要移动大量元素

基本操作

4.插入

Listinser(&Li,e)一将元素e插入到 的第i个位置

插入位置之后的元素都要后移

时间复杂度

最好0(1)、最坏O(n)、 平均O(n)

5.删除

ListDelete(&Li,&e)

将L的第i个元素删除,并用e返回

删除位置之后的元素都要前移

时间复杂度

最好0(1)、最坏O(n). '平均O(n)

6.代码要点

代码中注意位序和数组1下表的区别

算法要有健壮性,注意判断i和注意合法性

移动元素时,从靠前的元素开始?还是从表尾元素开始?

分析代码,理解为什么有的参数需要加"&"引用

7.按位查找

GetElem(Li)

获取表L中第i个位置的元素的值

用数组小标可得到第i个元素Ldata[i-1]
时间复杂度

最好/最坏/平均时间复杂度都是0(1)

8.按值查找

LocateElem(,e)

在顺序表L中查找第一个元素值等于e的元素, 并返回其位序

从第一个元素开始依次往后检索
时间复杂度

最好O(1)------目标元素在第一个位置

最坏O(n)------目标元素在最后一个人位置

平均O(n)------目标元素在每个位置的概率相同

表长难以预估、经常要增加/删除元素------链表

表长可预估、查询(搜索)操作较多------顺序表

相关推荐
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
阿史大杯茶1 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法
Chris _data1 小时前
二叉树oj题解析
java·数据结构
Lenyiin2 小时前
02.06、回文链表
数据结构·leetcode·链表
爪哇学长3 小时前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己3 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
烦躁的大鼻嘎3 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
C++忠实粉丝3 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
daiyang123...5 小时前
测试岗位应该学什么
数据结构
kitesxian5 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode