递归是一种函数遗产,因此将其与函数风格结合使用将产生最佳结果。在您的程序中,您已经使用命令式的mutable节点实现了一个链接列表,也就是说,data和{}的值可以随时间而变化。虽然这看起来像是一种直观的方法,但我想重点介绍一种将我们从严重的状态复杂性中解放出来的不可变的实现。我们将使用函数链表来实现函数。在
我们从简单的node和linked_list类开始。这次我们跳过了创建get_*和set_*函数。在Python中还有其他方法可以实现这种功能,稍后我们将看到class node:
def __init__ (self, left, right):
self.left = left
self.right = right
class linked_list:
def __init__ (self, node = None):
self.node = node
接下来,我们为列表定义基元properties:is_empty,head,和{}
^{2}$
现在,node的用法被完全抽象化了,我们可以通过使用我们的新属性来编写更高级的列表行为class linked_list:
...
def length (self):
if self.is_empty:
return 0
else:
return 1 + self.tail.length ()
在上面,我们可以看到,通过使用列表的属性来讨论我们的列表是非常容易的。在进一步讨论之前,让我们看看如何使用print构造列表并将其可视化。对于对象到字符串的转换,我们使用^{}class linked_list:
...
def add_first (self, x):
return linked_list (node (x, self))
def __str__ (self):
if self.is_empty:
return "None"
else:
return str (self.head) + " -> " + str (self.tail)
ls = linked_list().add_first(3).add_first(2).add_first(1)
print (ls)
# 1 -> 2 -> 3 -> None
print (ls.length ())
# 3
请记住,因为我们已经构建了一个不可变的链表,add_first是否会改变调用它的列表ls = linked_list().add_first(3).add_first(2).add_first(1)
print (ls)
# 1 -> 2 -> 3 -> None
print (ls.add_first (0))
# 0 -> 1 -> 2 -> 3 -> None
print (ls)
# 1 -> 2 -> 3 -> None
在我们继续之前,让我们更容易地构建我们的链接列表。我们添加了一个staticbuild函数,它允许我们构造一个由不同数量的输入组成的列表class linked_list:
...
@staticmethod
def build (x = None, *rest):
if x is None:
return linked_list ()
else:
return linked_list (node (x, linked_list.build (*rest)))
print (linked_list.build (1,2,3))
# 1 -> 2 -> 3 -> None
现在,让我们看看您的remove_first和remove_last函数class linked_list:
...
def remove_first (self):
if self.is_empty:
raise Exception ("cannot remove first element of an empty list")
else:
return self.tail
def remove_last (self):
if self.is_empty:
raise Exception ("cannot remove last element of an empty list")
elif self.tail.is_empty:
return self.tail
else:
return linked_list (node (self.head, self.tail.remove_last ()))
ls = linked_list.build (1,2,3)
print (ls)
# 1 -> 2 -> 3 -> None
print (ls.remove_first ())
# 2 -> 3 -> None
print (ls.remove_last ())
# 1 -> 2 -> None
print (ls)
# 1 -> 2 -> 3 -> None
和node_numberclass linked_list:
...
def node_number (self, index = 0):
if self.is_empty:
raise Exception ("index out of bounds")
elif index is 0:
return self.head
else:
return self.tail.node_number (index - 1)
ls = linked_list.build ("a", "b", "c")
print (ls.node_number (0))
# "a"
print (ls.node_number (1))
# "b"
print (ls.node_number (10))
# Exception: index out of bounds
还有一份免费赠品class linked_list:
...
def add_last (self, x):
if self.is_empty:
return self.add_first (x)
else:
return linked_list (node (self.head, self.tail.add_last (x)))
ls = linked_list.build (1, 2, 3)
print (ls)
# 1 -> 2 -> 3 -> None
print (ls.add_last (4))
# 1 -> 2 -> 3 -> 4 -> None
print (ls)
# 1 -> 2 -> 3 -> None
在repl.it进行完整的程序演示