赞
踩
在上一篇中我们学习了单向链表的实现,链表中我们除了单向链表还有双向链表,在这一篇我们将更进一步地了解链表,实现双向链表
双向链表是一种可以双向遍历的链表,它的指针可以指向前后两个方向的节点。双向链表拥有头节点和尾节点,可以从头节点进入链表进行操作,同时也可以从尾节点进入链表进行操作,下图便为双向链表的结构
与单链表不同的是,双向链表拥有两个指针prev(前一个节点)和next(下一个节点),比单链表多了一个指向前一节点的引用地址。双向链表的优点是,在操作链表中的上一节点时可以通过前指针直接向前遍历,而无需从头节点开始重新遍历,提高了链表的效率。其缺点是比单链表结构多了一个指针地址,会占用更多的内存来进行存储。
双链表看着复杂,不好理解,但它本质与单链表一样,方法的实现也与单链表基本相同,因此我们不需害怕,下面我会带你们一起实现,当你们看完就会说:哦!这什么丫?这么简单,这不跟单链表一样吗?
根据每一个节点,我们知道每个节点都拥有prev指针(指向前一个节点)和next指针 (指向后一个节点),因此我们的节点对象要包含val值,以及两个指针
双向链表拥有头节点和尾节点,它比单链表多了一个尾节点,在构造方法中我们需要注意的是,在初始化头尾节点时,我们要先创建节点,将它的val以及两个指针都赋值为null,然后再去更新头尾指针
若在创建中直接将head的指针指向tail,那head的next指针就会永为null,在后面的方法的书写中再去更新heed的指针就会报错(我第一次这样写,找这个bug找了一个小时\(`Δ’)/)
下面我们将实现双向链表中一些常用的方法,它们几乎与单链表一致
①add 在链表中添加元素
add方法有三种情况: addFirst(值) 在首部添加元素
add(值) 在尾部添加元素
add(值,索引) 在指定位置添加元素
这里我们先从第三种情况开始考虑
要知道,插入一个节点,我们要将新节点的指针更新,再将它指定位置的前一个节点的next指针以及指定位置的节点的prev指针断开,因此我们寻找位置时也要需要找到要插入位置的前一个节点
思路:我们首先创建一个新节点来储存val值,再定义一个下标i来寻找要插入的位置,找到位置后,更新新节点指针以及新节点前后节点的指针
这里我们再考虑其他两种边界情况
Ⅰ.addFirst 在首部添加元素
此时p即为head,n即为head的下一个节点,就是在0索引位置添加元素
Ⅱ.add 在尾部添加元素
此时p为tail的前一个节点,n为tail节点,就是在链表长度size位置添加元素
以上两种均为情况三的一种,因此我们就可以直接引用,从而简化代码
②get(索引) 获取指定位置元素
思路:定义一个下标i用来寻找位置,其实相当于数组的遍历,但我们可以从头节点位置开始寻找,也可以从尾节点位置开始寻找,这里我们从头节点开始
③remove(索引) 删除指定位置的元素
删除节点也存在三种情况
情况一:链表为空链表
情况二:要删除的节点处于尾节点位置
以上两种均为边界情况
情况三:要删除的节点不处于边界
我们先从情况三开始分析
思路:我们需要知道要删除节点的上一个节点以及下一个节点,再去更新指针
接下来我们来思考其他两种边界情况
Ⅰ.当链表为空时,我们直接抛出异常即可,不必再走循环
Ⅱ.当我们要删除的节点位于尾节点
尾节点是不能删除的
根据我们情况三的代码 ,此时p为An,n为null,null没有指针,那么这种情况不考虑的话程序就会报错,因此对于这种情况我们也要考虑
思路:若要删除的节点位于尾节点,直接抛出异常
写完代码后,是不是感觉这双向链表与单向链表几乎一样啊,下面我们来带入数据爽一下吧
各位都实现了吗?
注:若存在错误,不足之处,望各位指出更正₍˄·͈༝·͈˄*₎◞ ̑̑
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。