
(以下内容全部来自上述课程)

单链表的定义

1. 什么是单链表
上次我们说顺序表是名单上的学号,那么单链表就是教室中的散乱的同学们按随机的座位坐好。
座位随机,就代表数据不是连续的,也就是前后桌的学号不是连在一起的,但是还是可以利用学号(这里相当于地址)找到具体同学。

2. 用代码定义一个单链表
typedef:数组类型重命名。
单链表的定义:头插法or尾插法
需要插入的东西就是结点,单链表就是好多个结点连在一起的东西,所以我们先看结点定义。
2.1 结点定义
结点=数据域+指针域;
数据域:存储它的数据元素
指针域:存储下一个结点的地址值

新结点分配空间–>头结点√

typedef struct LNode LNode;typedef struct LNode *LinkList;LNode * L;LinkList L;
互相对照,一开始定义中有*,用这个别名定义别的就可以省略*。
一句话就是,竖着看,都只存在一个*。


2.2 单链表定义

3. 实现
3.1 不带头结点的单链表
不带头结点,初始化单列表的时候就可以不给它分配空间。
定义结点–>初始化空单链表–>无头结点

3.2 带头结点的单链表
定义结点–>初始化空单链表–>有头结点(分配空间)

3.3 对比
更倾向带头结点的定义方法。

4. 小结

单链表的插入删除

1. 插入
1.1 按位序插入
1.1.1 带头结点
记忆:取代某个结点的位置(i),就是在这个结点之前的位置(i-1)插入新的结点。

LNode *s =(LNode *)malloc(sizeof(LNode));:分配新的内存给s指针指的位置s->data =e;:表示s的数据域是元素es->next=p->next;:使p指针原本指的位置,赋值给s指针即将指向的位置,next就是指向的下一个结点
p原本指的是a1,也就是让s指向a1,也就是图中连起来的绿色的线p->next=s;:让p指向的下一个结点变为s,也就是图中黄色的线
补充:
- A->data:A的数据域
- ->:指向
- next:下一个结点
- A->next:A指向的下一个结点

如果绿色和黄色颠倒顺序: - 先是p指向的下一个结点变为s
- 然后把p指向的下一个结点赋值给s指向的下一个结点
- 就变成了s指向自己本身
- 所以千万不可以颠倒顺序!!!

如果插入在最后的位置,插入的元素指向的位置就是NULL。

如果插入的位置超出了单链表的长度,就会直接返回false。

平均时间复杂度是O(n)

1.1.2 不带头结点

插在表头就需要改变头指针(之前指向a1,现在指向插入的元素)
LNode *s =(LNode *)malloc(sizeof(LNode));:分配插入元素的内存s->data =e;:表明s的数据域是元素e。s->next=L;:L是头指针,所以就是L指向的下一个结点赋值给s指向的下一个结点,就是s指向a1,也就是绿线。L=S;:L指向s,也就是图中的黄线。

如果插入之后的位置是第一个位置之后,因为没有头结点,所以每次都需要记录一下指针此时指向的是哪个结点,除此之外,其余的和头结点的插入代码一模一样。

1.2 指定结点的后插操作
因为分配的空间比较随机,所以前后空间存不存在都是随机的,有的时候就可能分配失败。

如果分配失败,就直接返回false;
如果分配成功(右下角):
s->data =e;:s的数据域是元素es->next=p->next;:p指向的下一个结点赋值给s的指向的下一个结点(加一个往后指的线)p->next=s;:p指向的下一个结点变为s(加一个前面往这里的线)

1.3 指定结点的前插操作
指定结点的前插操作,就需要先找到他的前一个结点,然后再进行操作。
但是没办法找到前一个结点,循环太浪费时间,所以就找到此指定节点A的后一个结点B,在他们两个之间插入你想插入的结点X,然后把指定节点A和插入结点X的数据域互换一下,和指定节点的前插操作就是等价的效果。

- 大体思路是,x–>y,想变成e–>x–>y,就先变成x–>e–>y,xe互换数据域,变为e–>x–>y。
s->next=p->next;:p指向的下一个结点赋值给s指向的下一个结点(绿线)p->next=s;:p指向的下一个结点变为ss->data=p->data;:p的数据域赋值给s的数据域p->data=e;:p的数据域变为元素e

2. 删除
2.1 按位序删除

如果删除的是最后一个结点,就需要把它前一个结点指向NULL。

2.2 指定结点的删除
同样,先删掉指定节点的后一个结点,然后把指定节点的数据域,改成刚刚删除的结点的数据域。
嗯,无关先后顺序,差不多这个意思。

LNode *q=p->next;:p指向的后一个结点赋值给q结点p->data=p->next->data;:p指向的下一个结点的数据域赋值给p的数据域p->next=q->next;:q指向的下一个结点赋值给p指向的下一个结点


3. 小结


单链表的查找
只讨论带头结点的情况!

1. 按位查找
如果i=0,直接返回头指针的位置。

如果i=8,也就是查找单链表长度之外的元素,会直接返回p。




2. 按值查找
按值查找,就是条件中用数据域进行判断。



3. 小结

单链表的建立

1. 尾插法
定义结点–>初始化单链表

其实就是带头结点的指定节点的后插操作。



2. 头插法
逆向建立单链表,然后每次都是尾插,最后再倒过来。



3. 小结

双链表
所有操作就是比单链表多了一个prior,不再赘述。

1. 初始化
增加了一个prior,前一个结点。

2. 插入


3. 删除

4. 遍历

5. 小结

循环链表

1. 循环单链表




2. 循环双链表

2.1 初始化

2.2 插入

2.3 删除

4. 小结

静态链表

1. 什么是静态链表

2. 用代码定义一个静态链表


2. 简述基本操作的实现


4. 小结

顺序表 vs 链表

1. 逻辑结构

2. 存储结构

3. 基本操作





4. 选择?

5. 小结



315

被折叠的 条评论
为什么被折叠?



