双链表是在单链表的操作的基础上形成的,除了头插法、尾插法、插入、删除四个基本操作的代码略有不同外,其他的代码与单链表基本相同。
以下展示双链表结点类构建、双链表类构建、头插法、尾插法、插入、删除的操作。
class DLinkNode:#创建数字域,前后指针域
def __init__(self.data=None):
self.data=data
self.next=None
self.prior=None
class DLinkList:#实际上就是创建每个结点的前后关系
def __init__(self):
self.dhead=DLinkNode()
self.dhead.next=None
self.dhead.prior=None
插入的基本思想:
#插入结点都是这个思路,之后会衍生双链表出头插法和尾插法
s.next=p.next
p.next.prior=s
s.prior=p
p.next=s
删除基本操作:
#删除结点如下思路,只删除要删除对象所指向他的箭头即可
p.next.prior=p.prior
p.prior.next=p.next
头插法、尾插法、插入、删除四个基本操作如下:
#一般建表都是已知一个数组,然后将数组中的元素依次建立成一个双链表
#头插法建表
#重点是指向的建立
def CreateListF(self,a):
for i in range(0,len(a)):
s=DLinkNode(a[i])
s.next=self.dhead.next#相当于设置了插入的位置,s的next域指向之前头结点的next域的那个结点,也就是在头结点和头结点之后的那个结点中间插入一个结点
#self.dhead.next可能为空,如果是空的话,就置s.next域为空
if self.dhead.next!=None:#如果原来的表是空表,那么新加入的结点的next域置空,只需要建立head域的指针以及前一个结点的next域指向自身即可
# 如果序号i-1就是最后一个结点,那么s的next域就可以置为空,并且没有引用指向这个结点
self.dhead.next.prior=s
self.dhead.next=s
s.prior=self.dhead
#尾插法建表
#重点是指针
def CreateListR(self,a):
t=self.dhead#t这个指针始终指向最后一个结点,而一开始只有头结点所以先将就放在头结点
for i in range(0,len(a)):
s=DLinkNode(a[i])
t.next=s#一开始头结点的next域设置为s
s.prior=t#一开始s的prior域设置为头结点
t=s#指针后移一位
t.next=None
#在双链表中序号i的位置插入元素e
#实际上就是插入代码的完善
def Insert(self,i,e):
assert i >=0
s=DLinkNode(e)
p=self.geti(i-1)#用geti()获取序号i-1的结点,并用p标记,方便后续操作
assert p is not None
s.next=p.next#那么s的next域就可以置为空,不管之后有没有结点,都需要对这个next域进行操作
if p.next!=None:#如果序号i-1就是最后一个结点,那么s的next域就可以置为空,并且没有引用指向这个结点
p.next.prior=s
p.next=s
s.prior=p
#在双链表中删除序号i位置的元素
def Delete(self,i):
assert i>=0
p=self.geti(i-1)#用geti()获取序号i-1的结点,并用p标记,方便后续操作
assert p is not None
p.prior.next=p.next#要判断哪个箭头不管后面有没有结点,都要把箭头画出来
if p.next!=None:
p.next.prior=p.prior