python3实现双向链表图文详解

在上一节《python3实现单向链表图文详解》中我们实现了单向链表,但是单向链表受其只能从前往后进行遍历的限制,在有的时候效率并不是很高,例如需要从特定结点往前进行查询时。这一节我们就将其改进版本双向链表也来实现一下。当然单向链表的改进并不只有双向链表这一种,在以后的文章中我们再实现下单向循环链表甚至双向循环链表。

双向链表

和单向链表的结构比起来,双向链表的每个节点除了包含后继结点的地址,还包含前驱结点的地址

1-dll.png

这样在进行类似从某结点往前查找的时候就不用再从头遍历了,但是每个节点占用的内存就多了,属于是典型的空间换时间

下面直接看看代码实现。

python3实现

同样和单向链表一样,先搞定结点再搞定链表类。

结点类

只是比单向链表多个一个前驱的地址,加上一个实例属性即可

class Node(object):
    def __init__(self, value):
        self.value = value
        self.next = None
        self.prev = None

这里的prev就是前驱的地址,同样默认为None

链表类

构造函数没啥区别,同样是一个头地址即可,依然只供内部访问

属性 说明 类型
__head 指向第一个结点的地址 对象属性,仅内部使用

最后还是和单向链表一样实现下面这些方法

方法 说明 类型
isEmpty 链表长度为0返回True,否则返回False 对象方法
length 返回链表数据的长度 对象方法
travel 遍历整个链表,依次打印每个结点的值 对象方法
append 在链表尾端添加结点 对象方法
shift 在链表头部添加结点 对象方法
insert 在指定下标添加结点 对象方法
remove 删除第一次出现的某个值 对象方法
exist 检查某个值是否在链表中 对象方法

仔细想一想大家应该就能发现,这上面的isEmptylengthtravelexist这四个方法的实现逻辑并没有用到前驱结点的地址,所以和单向链表的实现方法是一模一样,完全不用改。

既然是面向对象,那我们完全可以import前面实现单向链表的类,继承下来实现双向链表,这样这四个方法就不用重写了,只需要关心另外的四个即可。

下面来逐一看看剩下的四个方法。

shift

从头插入结点,如下图所示

2-shift.png

还是秉承着先建立后断开的原则,第一步先将新结点的next指向原先的第一个结点,然后将self.__head指向新结点,最后将原先第一个结点的prev也指向新结点即可。

当然还是要考虑原先是空链表的特殊情况,这时候只需要将self.__head指向新结点即可。

def shift(self, value):
	node = Node(value)
	if self.isEmpty() == True:
		self.__head = node
	else:
		# link before break
		node.next = self.__head
		self.__head.prev = node
		self.__head = node
append

尾部插入就简单得多,同样也是游标移动到最后一个结点的时候,将原先最后节点的next指向新结点,不过这里要多的一步就是将新结点的prev也指向原先的最后结点。

同样也要考虑原先是空链表的特殊情况,也是直接将新结点赋值给self.__head即可

def append(self, value):
    node = Node(value)
    if self.isEmpty():
        self.__head = node
    else:
        cur = self.__head
        while cur.next != None:
            cur = cur.next
        cur.next = node
        node.prev = cur

只有最后一句代码是新加的。

insert

任意位置插入结点就稍微复杂一点,因为涉及到一共四根线的断开和连接

3-insert.png

同样秉承先建立后断开的原则,先将新结点的prevnext指向前后两个结点,然后再修改原先前驱结点的next以及后继结点的prev,指向新结点。

值得一提的就是,在单向链表中因为要操作前驱结点,游标只能提留在前驱结点上。而在双向链表中,则没有这个限制,游标可以在后继结点上。体现在代码上就是循环的退出条件

def insert(self, pos, value):
    """insert a node at specific position"""
    if pos 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值