#python #recursion #iteration
#python #рекурсия #итерация
Вопрос:
В чем разница в следующем коде? Ссылки относятся к объектам связанного списка. Атрибуты .first() и .rest() возвращают первое и остальные значения соответственно. В соответствии с политиками StackOverflow и политиками моего класса я хочу упомянуть, что это не задание — это было необязательное задание, которое было давно выполнено, и я возвращаюсь к нему, пробуя итерацию против рекурсии, чтобы подготовиться к предстоящему экзамену.
Вот несколько док-тестов.
>>> s = Link(1, Link(2, Link(3)))
>>> s.rest.rest.rest = s
>>> has_cycle(s)
True
>>> t = Link(1, Link(2, Link(3)))
>>> has_cycle(t)
False
>>> u = Link(2, Link(2, Link(2)))
>>> has_cycle(u)
False
Вот мое рекурсивное решение для функции def has_cycle(ссылка):
existing = []
def cycle(link):
nonlocal existing
if link is not Link.empty:
if link in existing:
return True
existing.append(link)
cycle(link.rest)
cycle(link)
return False
Альтернативно
existing = []
while link is not Link.empty:
if link in existing:
return True
existing.append(link)
link = link.rest
return False
Спасибо. Я должен упомянуть, что итеративная версия работает, рекурсивная версия — нет.
Класс списка ссылок:
class Link:
"""A linked list.
>>> s = Link(1, Link(2, Link(3)))
>>> s.first
1
>>> s.rest
Link(2, Link(3))
"""
empty = ()
def __init__(self, first, rest=empty):
assert rest is Link.empty or isinstance(rest, Link)
self.first = first
self.rest = rest
def __repr__(self):
if self.rest is Link.empty:
return 'Link({})'.format(self.first)
else:
return 'Link({}, {})'.format(self.first, repr(self.rest))
Комментарии:
1. Правильный ли отступ в вашем реальном коде?
2. Неверен ли размещенный мной отступ? Простите меня, я не совсем понимаю, на что вы ссылаетесь.
3. Я предполагаю, что
Link.empty
даетTrue
илиFalse
; если это так, ваше условиеif link is not Link.empty
никогда не будет выполняться, потому чтоlink
это неboolean
. Просто измените это условие наif not Link.empty
, и все готово.4. В этом случае итеративное решение никогда не должно работать? Но это так. Я не думаю, что это все.
5. Ну, тогда покажите нам свой
Link
класс 🙂 Э-э-э … и вы должныreturn cycle(link.rest)
(вернуть его результат, а не просто вызвать его).
Ответ №1:
existing = []
def cycle(link):
nonlocal existing
if link is not Link.empty:
if link in existing:
return True
existing.append(link)
cycle(link.rest)
else:
return False
res = cycle(link)
#print res
Попробуйте это как свою рекурсивную версию….
Комментарии:
1. Это сработало. Тьфу, это было просто. Спасибо за вашу помощь. Мне нужно было добавить еще один возврат к циклу (ссылка). Я пропустил, как работают возвраты в функциях более высокого порядка. Спасибо за ваше время.
Ответ №2:
Ваши возвраты отсутствуют или неуместны. При переходе к рекурсии вам необходимо вернуть соответствующий результат. Кроме того, вам нужно вернуть что-то на случай, если ваше условие emtpy не выполняется:
existing = []
def cycle(link):
nonlocal existing
if link is not Link.empty:
if link in existing:
return True
existing.append(link)
return cycle(link.rest) # Return result of recursive call
else:
return False # Return false if link is empty
print(cycle(link))
Комментарии:
1. Вы были правы!! Большое вам спасибо за ваше время. Мне нужно следить за моими результатами в функциях более высокого порядка и рекурсии. Спасибо