线性表List---链式存储结构
相关概念链式存储结构/链式表定义链式存储特点单链表单链表读取单链表插入单链表删除 时间复杂度单链表整表创建单链表整表删除 顺序存储与链式存储差异Python代码链接Java代码链接相关概念
链式存储结构/链式表
定义
数据域:存储数据元素的信息
指针域:存储直接后继位置,指针域中存储的信息叫做指针或链
结点Node:数据域+指针域
所以一般Node类设计:
//javaclass Node{int data; //数据域Node next; // 指针域Node(int val){//构造方法this.data = val;this.next = null;}}
# pythonclass 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的作⽤:记录下⼀结点,以便等当前结点释放后,把下⼀结点拿回来补充
顺序存储与链式存储差异
Python代码链接
本章节python相关代码链接
其中single_link_list.py 为顺序结构线性表
其他的文件可以看README.md里面有详解
Java代码链接
本章节python相关代码链接
其中SingleLinkList.java 为顺序结构线性表
其他的文件可以看README.md里面有详解
如果文章或者代码有问题,欢迎帮我指出,感激不尽,互勉~