需求
构建链表,并完成一下功能:
- 设置链表的头(head)和尾部(tail),也就是将其中的某个元素直接变成头和尾
- 在一个节点的特定位置(前/后)插入一个node,或者在一个特定的位置插入节点,假设head节点的位置为1
- 移除具有特定值的node
- 搜索具有特定值的node
Solution
# 节点包括本身的值和前后关系
class Node:
def __init__(self, value):
self.value = value
self.prev = None
self.next = None
# 对于一个双向链表对象,只负责记录头尾信息。
# 要查看前后的邻居必须深入进去
class DoublyLinkedList:
def __init__(self):
self.head = None
self.tail = None
#更改头部
#Time: O(1)|Space:O(1)
def setHead(self, node):
# 边界条件,头部是空的
if self.head is None:
self.head = node
self.tail = node
return
#否则执行在当前节点的头部前方进行插入,使用self.insertBefore
self.insertBefore(self.head, node)
#Time: O(1)|Space:O(1)
#设定尾部
def setTail(self, node):
# 边界条件,尾部是空的,此时同步和尾部都是新来的这个节点
if self.tail is None:
self.setHead(node)
return
#如果不是空的,在当前的tail后方插入节点
self.insertAfter(self.tail,node)
#Time: O(1)|Space:O(1)
# 实现前方插入
def insertBefore(self, node, nodeToInsert):
#这里 nodeToInsert是我们将要用来进行插入的node
if nodeToInsert == self.head and nodeToInsert == self.tail:
return
#否则先尝试移除这个已经存在的 nodeToInsert。如果存在
self.remove(nodeToInsert)
nodeToInsert.prev = node.prev
nodeToInsert.next = node
if node.prev is None:
self.head = nodeToInsert
else:
node.prev.next = nodeToInsert
node.prev = nodeToInsert
#Time: O(1)|Space:O(1)
def insertAfter(self, node, nodeToInsert):
if nodeToInsert == self.head and nodeToInsert == self.tail:
return
self.remove(nodeToInsert)
nodeToInsert.prev = node
nodeToInsert.next = node.next
if node.next is None:
self.tail = nodeToInsert
else:
node.next.prev = nodeToInsert
node.next = nodeToInsert
#Time: O(position)|Space:O(1)
def insertAtPosition(self, position, nodeToInsert):
if position == 1:
self.setHead(nodeToInsert)
return
node = self.head
current_position = 1
while node is not None and current_position != position:
node = node.next
current_position += 1
if node is not None:
self.insertBefore(node,nodeToInsert)
else:
self.setTail(nodeToInsert)
#Time: O(n)|Space:O(1)
def removeNodesWithValue(self, value):
node = self.head
while node is not None:
node_to_remove = node
node = node.next
if node_to_remove.value == value:
self.remove(node_to_remove)
#Time: O(1)|Space:O(1)
def remove(self, node):
if node == self.head:
self.head = self.head.next
if node == self.tail:
self.tail = self.tail.prev
self.removeNodeBindings(node)
#Time: O(n)|Space:O(1)
def containsNodeWithValue(self, value):
node = self.head
while node is not None and node.value != value:
node = node.next
return node is not None
#Time: O(1)|Space:O(1)
def removeNodeBindings(self,node):
if node.prev is not None:
node.prev.next = node.next
if node.next is not None:
node.next.prev = node.prev
node.prev = None
node.next = None
### show a linked list
def draw_linked_list(self):
delimeter = "<->"
node = self.head
while node is not None:
if node.next is not None:
print(node.value,end = delimeter)
node = node.next
else:
print(node.value,end = '\n')
return
linkList = DoublyLinkedList()
linkList.setHead(Node(1))
linkList.setTail(Node(6))
for i in reversed(range(2,6)):
linkList.insertAfter(linkList.head,Node(i))
# linkList.insertAfter(linkList.head,Node(2))
# linkList.insertAfter(Node(1),Node(2))
# 1<->5[Finished in 0.6s]
linkList.draw_linked_list()
linkList.insertBefore(linkList.tail,Node(3))
linkList.draw_linked_list()
linkList.insertBefore(linkList.head,Node(666))
linkList.draw_linked_list()
linkList.removeNodesWithValue(5)
linkList.draw_linked_list()
linkList_2 = DoublyLinkedList()
linkList_2.setHead(Node(111))
linkList_2.insertAfter(linkList_2.head,Node(222))
# linkList_2.setTail(Node(111))
linkList_2.draw_linked_list()
linkList_2.insertBefore(linkList_2.head,Node(111))
linkList_2.draw_linked_list()
Output
/Users/lianda_duan/Documents/pycharm_project/temp_can_delete/venv/bin/python /Users/lianda_duan/Documents/pycharm_project/temp_can_delete/main.py
1<->2<->3<->4<->5<->6
1<->2<->3<->4<->5<->3<->6
666<->1<->2<->3<->4<->5<->3<->6
666<->1<->2<->3<->4<->3<->6
111<->222
111<->111<->222
Process finished with exit code 0