概念:链表是通过指针关联的链式结构
注意:列表 list 底层是线性结构
单链表
--操作复杂度
linked_list.append(value) O(1)
linked_list.appendleft(value) O(1)
linked_list.find(value) O(n)
linked_list.remove(value) O(n)
class Node(object):
def __init__(self, value=None, next=None):
self.value = value
self.next = next
def __str__(self):
return '<None:value: {}, next = {}>'.format(self.value,self.next)
__repr__ = __str__
class LinkedList(object):
def __int__(self, maxsize=None):
self.maxsize = maxsize
self.root = Node()
self.tailnode = None
self.length = 0
def __len__(self):
return self.length
def append(self, value):
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
node = Node(value)
tailnode = self.tailnode
if tailnode is None:
self.root.next = node
else:
tailnode.next = node
self.tailnode = node
self.length += 1
def appendleft(self, value):
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
node = Node(value)
if self.tailnode is None:
self.tailnode = node
headnode = self.root.next
self.root.next = node
node.next = headnode
self.length += 1
def __iter__(self):
for node in self.iter_node():
yield node.value
def iter_node(self):
"""遍历从head到tail节点"""
curnode = self.root.next
while curnode is not self.tailnode:
yield curnode
curnode = curnode.next
if curnode is not None:
yield curnode
def remove(self, value):
prevnode = self.root
for curnode in self.iter_node():
if curnode.value == value:
prevnode.next = curnode.next
if curnode is self.tailnode: # 更新 tailnode
self.tailnode = prevnode
del curnode
self.length -= 1
return 1 # 表明删除成功
else:
prevnode = curnode
return -1 # 表明删除失败
def find(self, value):
index = 0
for node in self.iter_node():
if node.vallue == value:
return index
index += 1
return -1 #没找到
def popleft(self):
"""删除第一个链表节点"""
if self.root.next is None:
raise Exception('pop from empty LinkedList')
headnode = self.root.next
self.root.next = headnode.next
self.length -= 1
value = headnode.value
if self.tailnode is headnode:
self.tailnode = None
del headnode
return value
def clear(self):
for node in self.iter_node():
del node
self.root.next = None
self.length = 0
self.tailnode = None
def reverse(self):
"""反转列表"""
curnode = self.node.next
self.tailnode = curnode
prevnode = None
while curnode:
nextnode = curnode.next
curnode.next = prevnode
if nextnode is None:
self.root.next = curnode
prevnode = curnode
curnode = nextnode
def test_liked_list():
ll = LinkedList()
ll.append(0)
ll.append(1)
ll.append(2)
ll.append(3)
assert len(ll) == 4
assert ll.find(2) == 2
assert ll.find(-1) == -1
assert ll.remove(0) == 1
assert ll.remove(10) == -1
assert ll.remove(2) == 1
assert len(11) == 2
assert list(11) == [1, 3]
assert ll.find(0) == -1
ll.append(0)
assert list(11) == [0, 1, 3]
assert len(11) == 3
headvalue = ll.popleft()
assert headvalue == 0
assert len(ll) == 2
assert list(11) == [1, 3]
assert ll.popleft() == 1
assert list(11) == [3]
ll.popleft()
assert len(ll) == 0
assert ll.tailnode is None
ll.clear()
assert len(ll) == 0
assert list(ll) == []
def test_linked_list_remove():
ll = LinkedList()
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
print(list(ll))
def test_linked_list_append():
ll = LinkedList()
ll.appendleft(1)
ll.append(2)
assert list(ll) == [1, 2]
if __name__ == '__main__':
test_liked_list()
test_linked_list_remove()
test_linked_list_append()
双链表
--操作复杂度
cdll.append(value) O(1)
cdll.appendleft(value) O(1)
cdll.remove(node),注意这里参数是 node O(1)
cdll.headnode() O(1)
cdll.tailnode() O(1)
class Node(object):
__slots__ = ('value', 'prev', 'next')
def __init__(self, value=None, prev=None, next=None):
self.value, self.prev, self.next = value, prev, next
class CircularDoubleLinkedList(object):
'''
循环双端链表
多了个循环 把root的prev指向tail节点,串起来
'''
def __init__(self, maxsize=None):
self.maxsize = maxsize
node = Node()
node.next, node.prev = node, node
self.root = node
self.length = 0
def __len__(self):
return self.length
def headnode(self):
return self.root.next
def tailnode(self):
return self.root.prev
def append(self, value):
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
node = Node(value=value)
tailnode = self.tailnode() or self.root
tailnode.next = node
node.prev = tailnode
node.next = self.root
self.root.prev = node
self.length += 1
def appendleft(self, value):
if self.maxsize is not None and len(self) >= self.maxsize:
raise Exception('LinkedList is Full')
node = Node(value=value)
if self.root.next is self.root:
node.next = self.root
node.prev = self.root
self.root.next = node
self.root.prev = node
else:
node.prev = self.root
headnode = self.root.next
node.next = headnode
headnode.prev = node
self.root.next = node
self.length += 1
def remove(self, node):
'''
在lru_cache 里实际根据key保存整个node
'''
if node is self.root:
return
else:
node.prev.next = node.next
node.next.prev = node.prev
self.length -= 1
return node
def iter_node(self):
if self.root.next is self.root:
return
curnode = self.root.next
while curnode.next is not self.root:
yield curnode
curnode = curnode.next
yield curnode
def __iter__(self):
for node in self.iter_node():
yield node.value
def iter_node_reverse(self):
'''相比单链独有的反序遍历'''
if self.root.prev is self.root:
return
curnode = self.root.prev
while curnode.prev is not self.root:
yield curnode
curnode = curnode.prev
yield curnode
def test_double_link_list():
dll = CircularDoubleLinkedList()
assert len(dll) == 0
dll.append(0)
dll.append(1)
dll.append(2)
assert list(dll) == [0, 1, 2]
assert [node.value for node in dll.iter_node()] == [0, 1, 2]
assert [node.value for node in dll.iter_node_reverse()] == [2, 1, 0]
headnode = dll.headnode()
assert headnode.value == 0
dll.remove(headnode)
assert len(dll) == 2
assert [node.value for node in dll.iter_node()] == [1, 2]
dll.appendleft(0)
assert [node.value for node in dll.iter_node()] == [0, 1, 2]
if __name__ == '__main__':
test_double_link_list()
网友评论