一种更为复杂的链表是“双向链表”或“双面链表”。
每个节点的两个链接:一个指向前一个节点,当前节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。
参考代码:
# from learn_3_slist_learn import SingleLinkList
class Node(object):
""" 节点 """
def __init__(self, item):
self.elem = item
self.prev = None
self.next = None
# 由于单链表是双链表的扩充,故可以采用继承的方法,但由于SingleLinkList中的__head是前双下划线(严重私有变量,连子类都访问不了),故此处不用继承的方法。
class DoubleLinkList():
""" 双链表 """
def __init__(self, node=None):
# 链表头是自己用的,不让用户访问,故使用私有(前双下划线是严重私有,连子类都用不了)
self.__head = node
def is_empty(self):
""" 判断链表是否为空 """
return self.__head is None
def length(self):
""" 返回链表的长度 """
cur = self.__head # cur 游标,用来遍历链表中的节点
count = 0 #用来记录数的数
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
""" 遍历整个链表 """
cur = self.__head
while cur != None:
print(cur.elem, end=' ') # 用空格代替换行
cur = cur.next
def add(self, item):
# 时间复杂度 O(1)
""" 链表头部添加元素 (头插法)"""
node = Node(item)
node.next = self.__head
self.__head.prev = node
self.__head = node
def append(self, item):
# 时间复杂度O(n)
""" 链表尾部添加元素 (尾插法)"""
node = Node(item)
# 判断链表是否为空
if self.is_empty(): # 如果为空
self.__head = node # 就把链表的头部指向这个新节点(node)
else: # 链表不空
cur = self.__head
while cur.next != None: # 遍历链表,找到最后一个节点(最后一个节点的特点就是,它的next域是None)
cur = cur.next
cur.next = node # 将新节点加入链表尾部
node.prev = cur
def insert(self, pos, item): # pos 的数数也是从0开始
""" 指定位置添加元素
:param pos 从0开始
"""
# 由于pos是用户传入的,故要对pos的值进行考虑
if pos <= 0: # 认为用户要在链表头部插入,即为头插法
self.add(item)
elif pos > (self.length()-1): #认为用户想要在链表尾部插入,即为尾插法
self.append(item)
else:
node = Node(item)
count = 0
cur = self.__head
#遍历找位置
while count < pos:
count += 1
cur = cur.next
# 当循环退出后,在当前位置进行插入
node.next = cur
node.prev = cur.prev
cur.prev.next = node
cur.prev = node
def remove(self, item):
""" 删除节点 (遇到的第一个节点) """
cur = self.__head
while cur != None:
if cur.elem == item:
# 对于头节点要特别判断
if cur == self.__head:
self.__head = cur.next
if cur.next:
#判断链表是否只有一个节点
cur.prev = None
else:
cur.prev.next = cur.next
if cur.next:
cur.next.prev = cur.prev
return True
else:
cur = cur.next
return False
def search(self, item):
""" 查找节点是否存在 """
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
# 加入测试
if __name__ == "__main__":
ll = DoubleLinkList()
print(ll.is_empty())
print(ll.length())
print("*"*50)
ll.append(1)
print(ll.is_empty())
print(ll.length())
print("*"*50)
ll.append(2)
ll.append(2)
ll.append(2)
ll.append(2)
ll.append(2)
ll.add(8) # 8 1 2 2 2 2 2
#!! 对程序进行测试时,要考虑所有情况,特别是边界情况
ll.insert(-1, 9) # 9 8 1 2 2 2 2 2
ll.insert(0, 100) # 100 9 8 1 2 2 2 2 2
ll.insert(2, 200) # 100 9 200 8 1 2 2 2 2 2
print(ll.is_empty())
print(ll.length())
print("遍历链表:")
ll.travel()
ll.insert(6, 600) # 100 9 200 8 1 2 600 2 2 2 2
# ll.insert(100, 1000)
print()
print("遍历链表:")
ll.travel()
# 测试search
print()
print("查找元素600", ll.search(600))
print("查找元素500", ll.search(500))
print("查找元素9", ll.search(9))
# 测试remove
print("先遍历当前链表:")
ll.travel()
print("\n删除2", ll.remove(2))
ll.travel()
print("\n删除9", ll.remove(9))
ll.travel()
print("\n再删除2", ll.remove(2))
ll.travel()
print("\n删除100", ll.remove(100))
ll.travel()