链表
双向链表
“双向链表”()或“双面链表”):每个节点有两个链接:一个指向前一个节点,当此节点为头节点时,指向空值;而另一个指向下一个节点,当此节点为尾节点时,指向空值。
节点实现
比单向列表多一个self.pre的链接
class Node():
def __init__(self,item):
self.prev=None
self.elem=item
self.next=None
单链表的操作
操作 | 表示 |
---|---|
is_empty() | 链表是否为空 |
length() | 链表长度 |
travel() | 遍历整个链表 |
add(item) | 链表头部添加元素 |
append(item) | 链表尾部添加元素 |
insert(pos, item) | 指定位置添加元素 |
remove(item) | 删除节点 |
search(item) | 查找节点是否存在 |
代码示例:
构造函数和单向链表一样,由于是否为空,长度返回,遍历都与pre链接无关,所以和单向链表相同。
class DoubleLinkList():
def __init__(self,node=None):
self.__head=node
d def is_empty(self):
"""链表是否为空"""
return self.__head==None
def length(self):
"""链表长度"""
cur=self.__head
count=0 #匹配下面cur!=None
while cur!=None: #此时若头节点为空也符合,若cur.next!=0,应该count初始值设为1,还需考虑头节点
count+=1
cur=cur.next
return count
def travel(self):
"""遍历整个链表"""
cur=self.__head
while cur!=None:
print(cur.elem,'\t')
cur=cur.next
def search(self,item) :
"""查找节点是否存在"""
cur=self.__head
while cur!=None:
if cur.elem==item:
return True #返回,所以后面不用break
else:
cur=cur.next
return False
也可用继承来解决,但是self.__head作为父类的私有属性,在后面调用时都需要改成self._父类名__私有属性名
class DoubleLinkList(SingleLinkList):
def __init__(self, node=None):
super().__init__(node)#若写成self.__head = node,node传入的是双链表的私有属性,将无法与单链表函数中的私有属性对应
# 继承单链表的判空
# 继承单链表的长度
# 继承单链表的遍历
链表头部添加元素
def add(self,item):
"""链表头部添加元素,头插法"""
node=Node(item)
node.next=self.__head #一般先用新节点去建立链接,以免破坏了原有链表的链接
self.__head=node
node.next.prev=node
#代码不唯一,如下代码也可行
# node.next=self.__head
# self.__head.prev=node
# self.__head=node
链表尾部添加元素
def append(self,item):
"""链表尾部添加元素,尾插法"""
node=Node(item)
if self.is_empty():
self.__head=node
else:
cur=self.__head
while cur.next!=None:
cur=cur.next
cur.next=node
node.prev=cur #只添加这句即可
指定位置添加元素
def insert(self,pos, item):
"""指定位置添加元素
:params 从0开始
"""
if pos<=0:
self.add(item) #self不要落
elif pos>(self.length()-1): #注意这里不包含等号
self.append(item)
else:
node=Node(item)
cur=self.__head
count=0
while count<pos:
cur=cur.next
count+=1
node.next=cur #一般先用新节点去建立链接,以免破坏了原有链表的链接
node.prev=cur.prev
cur.prev.next=node
cur.prev=node
#代码不唯一,如下代码也可行,要注意先打断的联系是哪个
# cur.prev=node
# node.prev.next=node
删除元素
还要考虑特殊情况,原列表中只有一个节点,且该节点需要删除和需要删除的节点为最后一个节点。此时cur.prev是不存在的,需要另外考虑。
def remove(self,item) :
"""删除节点"""
cur=self.__head
while cur!=None:
if cur.elem==item:
if cur==self.__head: #也可用pre==None 来判断
self.__head=cur.next
if cur.next:
cur.next.prev=None
else:
cur.prev.next=cur.next
if cur.next:
cur.next.prev=cur.prev
break
cur=cur.next