Рекурсия - это функциональное наследие, поэтому написание нашей программы в функциональном стиле дает наилучшие результаты. Это означает, что мы избегаем таких вещей, как изменение списка узлов, head.next = ...
. Ваш конструктор должен иметь возможность установить val
и next
-
class node:
def __init__(self, val, next = None):
self.val = val
self.next = next
def create_llist(v = None, *vals):
if not v:
return None
else:
return node(v, create_llist(*vals))
def llist_to_str(l = None):
if not l:
return "None"
else:
return f"{l.val} -> {llist_to_str(l.next)}"
print(llist_to_str(create_llist(1, 2, 3)))
# 1 -> 2 -> 3 -> None
Но create_llist
и llist_to_str
, вероятно, будут более согласованными, если мы реализуем их как частькласса. И, возможно, лучше назвать llist
, для «связанного списка» -
class llist:
def __init__(self, val, next = None):
self.val = val
self.next = next
def create(v = None, *more):
if not v:
return None
else:
return llist(v, llist.create(*more))
def __str__(self):
return f"{self.val} -> {self.next}"
print(llist.create(1, 2, 3))
# 1 -> 2 -> 3 -> None
Вместо того, чтобы полагаться на побочные эффекты, функции принимают входные данные и выдают выходной. В результате обратите внимание, что наш разум свободен от сложности -
class llist:
# ...
def map(node = None, f = lambda x: x):
if not node:
return None
else:
return llist(f(node.val), llist.map(node.next, f))
print(llist.map(llist.create(7, 8, 9), lambda x: x * x))
# 49 -> 64 -> 81 -> None