1.概念:
线性结构: 内存连续,下标结构
链式结构: 不连续,无下标,append(追加方便)find(遍历)
单链结构: root ( 入口) --> head(头节点)–>node/next( 节点和指针)–>… tail (尾节点)
2 数据和方法
单链表需要的数据是:构造节点,长度
linked list data : root ,length
方法有:初始化,增加,左侧增加,迭代节点,移除,查找,右边弹出
method: init , append, append left, iter_node, remove, find, popleft
3代码实现:
class Node(object):
def __init__(self, value=None, next=None):
self.value, self.next = value, next
class LinkedList(object):
def __init__(self, maxsize=None):
#初始化,长度,生成节点,尾结点目前是空
self.maxsize = maxsize
self.root = Node()
self.length = 0
self.tailnode = None
def __len__(self):
# 返回长度
return self.length
def append(self, value):
# 增加节点
if self.maxsize is not None and len(self) > self.maxsize:
# 判断链表是否已经最大,返回满了
return Exception("Full")
node = Node(value) # 将值作为一个节点
tailnode = self.tailnode # 再声明一下尾结点
if tailnode is None: # 没有尾结点,就是说这是第一个节点,
# 第一个插入的值作为root入口的下一个节点。即作为根节点的下一个节点,为头结点。
self.root.next = node
else:
tailnode.next = node # 后面每加一个值就作为尾节点。
self.tailnode = node # 当前加入的节点赋值给尾结点。
self.length += 1 # 长度加1
def appendLeft(self, value):
# 从左侧加一个节点
headnode = self.root.next # 借用一个中间变量放老的头结点
node = Node(value) # 将当前值生成节点值
self.root.next = node # 将当前节点作为根节点的下一个节点。
node.next = headnode # 当前节点的下一个节点就是老的头结点。
self.length += 1 # 长度加1
def iter_node(self):
# 遍历节点,每次返回当前节点的下一个节点
currnode = self.root.next
while currnode is not self.tailnode:
yield currnode
currnode = currnode.next
yield currnode # 返回最后的尾节点
def __iter__(self): # 需要和上面函数配合完成遍历节点
for node in self.iter_node():
yield node.value # 生成节点的值
def remove(self, value): # O(n)
# 移除一个节点
prenode = self.root
currnode = self.root.next
while currnode.next is not None: # 在到最后一个节点之前
if currnode.value == value: # 如果找到要删除的节点
prenode.next = currnode.next
# 让当前节点的前一个节点的next指向当前节点的下一个节点
del currnode # 删除这个节点
self.length -= 1 # 长度减1
return
def find(self, value): # O(n)
# 查找也是从头到尾遍历一遍
index = 0
for node in self.iter_node():
if node.value == value:
return index # 找到了,返回他的下标。
index += 1
return -1
def popleft(self): # O(1)
if self.root.next is None: # 先判断是不是空
raise Exception("pop from empty.")
headnode = self.root.next # 头结点
self.root.next = headnode.next #根节点的next指向头结点的next
self.length -= 1 # 长度减一
value = headnode.value
del headnode
return value
def clear(self): # 清除节点,全部删除
for node in self.iter_node():
del node
self.root.next = None
self.length = 0
def test_linked_list():
ll = LinkedList()
ll.append(0)
ll.append(1)
ll.append(2)
assert len(ll) == 3
assert ll.find(2) == 2
assert ll.find(3) == -1
ll.remove(0)
assert len(ll) == 2
assert ll.find(0) == -1
assert list(ll) == [1, 2]
ll.appendLeft(0)
assert list(ll) == [0, 1, 2]
assert len(ll) == 3
headvalue = ll.popleft()
assert headvalue == 0
assert len(ll) == 2
assert list(ll) == [1, 2]
ll.clear()
assert len(ll) == 0
4然后使用pytest 做单测:
命令行 pytest +文件名 会自动运行测试以test_开头的函数。