双向链表
设计思路
- 整体设计分为两个类, 一个是节点类, 每个节点作为一个对象; 另一个是链表类, 根据相邻节点间关系(上一个可以找到下一个, 下一个可以找到上一个, head 节点和 tail 节点为 None), 实现对各个节点间关系的操作, 包括append, insert, pop, remove等
- 第二阶段将设计好的类封装成容器
- 整体代码看似复杂, 实际理解发现并非如此, 理清节点间关系就好啦 …
class ListNode:
def __init__(self, item, next=None, prev=None):
self.item = item
self.next = next
self.prev = prev
def __repr__(self):
return "{} <== {} ==> {}".format(
self.prev.item if self.prev else None,
self.item,
self.next.item if self.next else None
)
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def append(self, item):
node = ListNode(item)
if self.head is None:
self.head = node
else:
self.tail.next = node
node.prev = self.tail
self.tail = node
return self
def insert(self, index, item):
if index < 0:
raise IndexError
current = None
for i, node in enumerate(self.iternodes()):
if i == index:
current = node
break
else:
self.append(item)
return
# break 找到
node = ListNode(item)
prev = current.prev
next = current
if i == 0: # 开头
self.head = node
else: # 不是开头
prev.next = node
node.prev = prev
node.next = next
next.prev = node
def pop(self): # 尾部移除
if self.tail is None: # 空
raise Exception
node = self.tail
item = node.item
prev = node.prev
if prev is None: # 仅一个元素
self.head = None
self.tail = None
else:
prev.next = None
self.tail = prev
return item
def remove(self, index):
if self.tail is None:
raise Exception
if index < 0:
raise IndexError
current = None
for i, node in enumerate(self.iternodes()):
if i == index:
current = node
break
else:
raise IndexError
prev = current.prev
next = current.next
# 4 种情况
if prev is None and next is None: # 1个节点
self.head = None
self.tail = None
elif prev is None: # 头
self.head = next
next.prev = None
elif next is None: # 尾
self.tail = prev
prev.next = None
else: # 中间
prev.next = next
next.prev = prev
del current
def iternodes(self, reverse=False):
current = self.tail if reverse else self.head
while current:
yield current
current = current.next if not reverse else current.prev
改进
## 容器化
class ListNode:
def __init__(self, item, next=None, prev=None):
self.item = item
self.next = next
self.prev = prev
def __str__(self):
return "{} <== {} ==> {}".format(
self.prev.item if self.prev else None,
self.item,
self.next.item if self.next else None
)
__repr__ = __str__
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
self._size = 0
def append(self, item):
node = ListNode(item)
if self.head is None:
self.head = node # 开头节点
else:
self.tail.next = node # 更新当前tail 节点的next
node.prev = self.tail
self.tail = node # 设置新tail
self._size += 1
return self # 链式编程
def insert(self, index, item):
# if index < 0:
# raise IndexError
#
# current = None
# for i, node in enumerate(self.iternodes()):
# if i == index:
# current = node
# break
# else:
# self.append(item)
# return
if index >= len(self):
self.append(item)
return
if index < -len(self):
index = 0
current = self[index]
# break 找到
node = ListNode(item)
prev = current.prev
next = current
if prev == None: # 开头
self.head = node
else: # 不是开头
prev.next = node
node.prev = prev
node.next = next
next.prev = node
self._size += 1
def pop(self): # 尾部移除
if self.tail is None: # 空
raise Exception
node = self.tail
item = node.item
prev = node.prev
if prev is None: # 仅一个元素
self.head = None
self.tail = None
else:
prev.next = None
self.tail = prev
self._size -= 1
return item
def remove(self, index):
if self.tail is None: # 空链表
raise Exception
# if index < 0:
# raise IndexError
#
# current = None
# for i, node in enumerate(self.iternodes()):
# if i == index:
# current = node
# break
# else:
# raise IndexError
current = self[index]
prev = current.prev
next = current.next
# 4 种情况
if prev is None and next is None: # 1
self.head = None
self.tail = None
elif prev is None: # 头
self.head = next
next.prev = None
elif next is None: # 尾
self.tail = prev
prev.next = None
else:
prev.next = next
next.prev = prev
del current
self._size -= 1
def iternodes(self, reverse=False):
current = self.tail if reverse else self.head
while current:
yield current
current = current.next if not reverse else current.prev
size = property(lambda self: self._size)
# 容器化
def __len__(self):
return self._size
# def __iter__(self):
# yield from self.iternodes()
__iter__ = iternodes
def __reversed__(self): # 解决reversed 内建函数调用
return self.iternodes(True)
def __getitem__(self, index):
if index >= len(self) or index <= -len(self):
raise IndexError
reverse = False if index >= 0 else True
start = 0 if index >= 0 else 1
for i, node in enumerate(self.iternodes(reverse), start):
if i == abs(index):
return node
def __setitem__(self, index, value):
self[index].item = value
ll = LinkedList()
ll.insert(0, 'start')
ll.insert(1000, 'end')
for x in ll:
print(x)
print('-' * 30)
print(ll[1], len(ll))
print()
for x in reversed(ll):
print(x)
运行结果
None <== start ==> end
start <== end ==> None
------------------------------
start <== end ==> None 2
start <== end ==> None
None <== start ==> end
False
------------------------------
None <== start~~~~ ==> end
start~~~~ <== end ==> None