线性表List---链式存储结构
相关概念
链式存储结构/链式表
定义
数据域:存储数据元素的信息
指针域:存储直接后继位置,指针域中存储的信息叫做指针或链
结点Node:数据域+指针域
所以一般Node类设计:
//java
class Node{
int data; //数据域
Node next; // 指针域
Node(int val){
// 构造方法
this.data = val;
this.next = null;
}
}
# python
class Node(Object){
def __init__(self, val):
self.data = val;
self.next = None;
}
n个结点链成一个链表,即为线性表的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表
头指针:链表中第一个结点的存储位置
头结点:在单链表的第一个结点前附设一个结点(头结点数据域可以不存储任何信息,头
结点的指针域存储指向第⼀个结点的指针)
头指针 | 头结点 |
---|---|
头指针是指链表指向第⼀个结点的指针,若链表有头结点,则是指向头结点的指针 | 为了⽅便操作⽽设⽴,放在第⼀元素的结点之前,数据域⼀般⽆意义(可存放链表⻓度) |
头指针具有标识作⽤,通常⽤头指针作为链表的名字 | 有头结点后对于第⼀元素结点的插⼊和删除与其他结点⽆异) |
⽆论链表是否为空,头指针均不为空。头指针是链表的必要元素 | 头结点⾮必需 |
链式存储特点
⽤⼀组任意的存储单元存储线性表的数据元素,存储单元可以是连续的也可以是不连续的,所以数据元素可以存在内存未被占⽤的任意存储位置
单链表
注:下文中提到的length为链表长度/链表有效元素个数
单链表读取
- 声明⼀个结点p指向链表第⼀个结点,初始化i从1开始;
- 当i<length时,遍历链表,让p指针向后移动不断指向下⼀结点,i++;
- 若到链表末尾p为空,则说明第i个元素不存在;
- 否则查找成功,返回结点p的数据。
单链表插入
- 声明⼀个结点p指向链表第⼀个结点,初始化i从1开始;
- 当i<length时遍历链表,p指针向后移动不断指向下⼀个结点,i++
- 当遍历到链表尾p为空,说明第i个元素不存在
- 否则查找成功,⽣成空结点s
- 将要插⼊的结点赋值给s→data
- 单链表的标准插⼊:
s→next=p→next;
p→next=s;
(如果交换语句顺序:p→next=s;s→next=p→next; 会导致,
p→next⾸先会被覆盖成s的地址,那么s→next=s,
此时原本的p→next就没有了上级,链表造成断链) - 返回成功
单链表删除
- 声明⼀个结点p指向链表的第⼀个结点位置,初始化i从1开始
- 当i<length时遍历链表,指针p后移,i++
- 当到链表尾部p尾空,说明第i个元素不存在
- 否则查找成功,将要删除的结点赋值为q,即p→next=q
- 删除p→next = q→next(其实4、5步综合来看就是p→next=p→next→next; 只是
我们需要删除的结点data值,多了⼀个变量缓存它) - 将q结点的data值赋值给e,等待返回
- 释放q结点(一般来说c c++就要手动释放,java和python有自动回收机制)
- 返回e
时间复杂度
遍历查找第i个元素+插入/删除元素,都为O(n)
情况:当从第i个位置 插⼊10个元素
顺序表:每次都要移动n-i个元素,每次都是O(n)
单链表:只需要第⼀个找到第i个位置的指针此时为O(n),接下来都是移动指针,时间复
杂度都为O(1)
总结:插⼊或删除越频繁,单链表优势会更⼤
单链表整表创建
- 声明⼀结点p和计数器变量i;
- 初始化空链表L
头插法
(3). 让L的头结点的指针指向NULL,建⽴⼀个带头结点的单链表
(4). 循环p:
a. ⽣成新的结点赋值给p;
b. 随机⽣成数字赋值给p的数据域p→data
c. 将p插⼊到头结点与前⼀新结点之间
尾插法
(3). 新建r指向尾部结点 r=*L
(4). 循环p:
a. ⽣成新的结点p
b. 随机⽣成数字赋值给p的数据域p→data
c. 将表尾终端结点的指针指向新指针 r→next=p
d. 将当前的新结点定义成表尾终端结点 r=p
(5). 将最后链表的指针域置空,明晰尾部 r→next=NULL
单链表整表删除
- 声明结点p和q
- 将第⼀个结点赋值为p
- 循环p:
a. 将下⼀结点赋值给q
b. 释放p
c. 将q赋值p - 最后将头结点指针域置为空
q的作⽤:记录下⼀结点,以便等当前结点释放后,把下⼀结点拿回来补充
顺序存储与链式存储差异
存储分配⽅式 | 时间性能 | 空间性能 |
---|---|---|
顺序存储⽤⼀段连续的存储单元依次存储线性表的数据元素 | 查找:顺序存储O(1) 单链表O(n) | 顺序存储需预分配存储空间,分⼤了,浪费,分⼩了容易发⽣上溢 |
单链表采⽤链式存储结构,⽤⼀组任意的存储单元存放元素 | 插⼊删除:顺序存储结构需要平均移动表⻓⼀半的元素O(n)单链表找出某位置的指针后,插⼊和删除为O(1) | 单链表不需要分配存储空间,只要有就可以分配,元素个数不受限制 |
Python代码链接
本章节python相关代码链接
其中single_link_list.py 为顺序结构线性表
其他的文件可以看README.md里面有详解
Java代码链接
本章节python相关代码链接
其中SingleLinkList.java 为顺序结构线性表
其他的文件可以看README.md里面有详解
如果文章或者代码有问题,欢迎帮我指出,感激不尽,互勉~