一.单链表的概念
1.概念
单链表是一种物理存储结构是非连续,非线性的但是在逻辑结构上是连续且线性的,链表是通过一个个结点来实现的,使每个相邻结点之间存在一定关系来将所有结点串起来,在物理存储上像是一条链子。
2.链表的原理
刚刚有说链表是通过结点之间的关系串起整个链表,那么具体是什么关系呢?🤔往下看:
单链表的每个结点分成两部分分别是储存数值域(val)和下一个结点的地址域(next),每个结点都储存这下一个结点的地址,这样是不是就可通过上一个结点找到下一个结点了一次类推就把整个链表连起来了。
接下来我们通过画图来具现化这个链表:
二.单链表的实现
1.单链表的创建
既然每一个结点都是一个引用类型,那么我们就可以定义一个内部类来创建结点。然后我们需要定义一个头节点,这个结点是整个链表的第一个结点,我们可以通过头节点来访问到链表中的每一个节点。链表不像顺序表可以随机下标访问,他只能通过都节点一点点遍历找到目标结点。
//node.next就可以找到下一个结点🥰
2.打印链表
我们要打印链表,首先肯定要遍历链表,刚刚说要通过头节点来找到后面节点,那是不是直接一直head = head.next就行?这样可以完成遍历可是头节点变成了最后一个结点,还怎么找到链表的头呢,所有我们定义一个中间变量 cur = head,然后让cur代替 head向后遍历。
3.尾插
首先创建一个新结点,通过cur遍历到最后一个结点,让最后一个结点连上新节点(cur.next = node)
//记得不要忘记判断链表是否为空哦!!!
4.头插
创建一个新节点,让新节点的下一个为head(node1.next = head)然后把新结点当作头结点
5.指定位置插入
通过cur遍历到指定位置然后插入新节点就行,不过该怎么插呢直接让cur的下一个等于新结点吗?这样的化就找不到后面的结点了,所以这里让新节点的next等于cur的next,然后再让cur的next,等于新结点。这里我画一个图来帮助你理解:
//记得判空哦!!
//如果要插入的位置是头部或者尾部直接头插或者尾插就行
6.获取链表长度
记录遍历了多少个结点就行
7.头删
将头结点置为下一个
8.尾删
遍历到倒数第二个位置然后将他的next置为null
//记得判空,如果链表只有一个结点那么我们可以直接调用刚刚的头删方法
9.指定位置删
先找到要删除的结点的前一个结点,然后直接让这个结点直接指向要删除的结点的后一个结点
//要先判断位置是否合法,和之前一样如果是头部或尾部直接头删尾删就行
10.删除指定数据val
一一遍历链表直到找到val为止(判断条件不能是cur.val != null,不然会越界)
//因为无法判断到头结点位置所有要单独判断
11.删除所有val
遍历数组找到所有val然后删除
//注意,这里必须要在遍历完了之后再判断头结点,否则如果头结点是val的话,进行头删第二个结点就会遍历不到;
12.清空链表
这个应该不用我多说了吗,嘿嘿!!😉
13.修改指定位置的数据val
到这里我想你应该已经对链表比较熟悉了吧,试着自己去实现一下把!🙉😋
三.和顺序表的对比
顺序表的优缺点:
优点:存储空间连续方便下标随机储存
缺点:头插或者中间插入数据要挪动后面数据,效率低下
链表优缺点:
优点:随用随分配内存,易于插入和删除
缺点:遍历困难,不易查找复杂度为o(N)
我们可以看到顺序表和链表的优缺点似乎是互补的
到这里链表就已经聊完了,小编这里只是实现了一个单链表,还有双链表,带头链表,循环链表等感兴趣的话可以自己去了解一下,核心思想都差不多
如果想要练习一些题,欢迎关注博主的刷题博客哦!最后如果有不懂的或者其他间接欢迎在下方评论或私信博主,谢谢你的阅读,也希望可以支持一下博主!!🥰🥰