#python #list #binary-tree #generator
#питон #Список #двоичное дерево #генератор
Вопрос:
Я пытаюсь вернуть значения всех листьев в двоичном дереве с помощью генератора и поместить полученные значения в список. Это мой рекурсивный код, который использует операторы yield, но я не знаю, как вернуть конечные значения с помощью генератора. Второй фрагмент кода под названием «Предыдущий код» показывает тот же код с операторами печати, который выводит правильные значения, поэтому единственная проблема-генератор. Как примечание, этот код использует root.left и root.right импортированы из класса двоичного дерева и, похоже, работают правильно. Заранее благодарю вас за любую помощь!!
Мой код
def leaves_list(self): def find(root): if not root: yield if not root.left and not root.right: yield root.data if root.left: find(root.left) if root.right: find(root.right) # my attempt a = find(self.root) lst = [] for i in a: lst.append(next(a)) return find(self.root)
Предыдущий Код
def leaves_list(self): def find(root): if not root: return if not root.left and not root.right: print(root.data, end = " ") return if root.left: find(root.left) if root.right: find(root.right) return find(self.root)
Это мой код тестера, и он должен возвращать список [5, 1, 8, 4]
.
Код тестера
root = LinkedBinaryTree.Node(3) T = LinkedBinaryTree(root) a = LinkedBinaryTree.Node(2) a.parent = root root.left = a b = LinkedBinaryTree.Node(7) b.parent = root root.right = b c = LinkedBinaryTree.Node(9) c.parent = a a.left = c d = LinkedBinaryTree.Node(5) d.parent = c c.left = d e = LinkedBinaryTree.Node(1) e.parent = c c.right = e f = LinkedBinaryTree.Node(8) f.parent = b b.left = f g = LinkedBinaryTree.Node(4) g.parent = b b.right = g print(T.leaves_list())
Комментарии:
1. Это трудно отладить без классов дерева и узлов, но я бы заметил, что
lst.append(next(a))
это должно бытьlst.append(i)
так, как есть, вы пропускаете все остальные значения.2. Вы делаете это, чтобы попрактиковаться в генераторах, или вам просто интересно получить список? Потому что простая версия генератора неэффективна.
Ответ №1:
Есть несколько проблем с вашей попыткой:
find(self.root)
вызывается дважды. В этом не должно быть необходимости, так как он выполнит работу дважды, чтобы снова получить тот же результатlst
создается и заполняется, но никогда не используется. Тебе, наверное, стоит его вернуть.- Не используйте итератор как с
for
циклом, так и с повторными вызовамиnext()
. Когда вы делаете это, вы фактически переходите к следующему значению дважды на каждой итерации, тем самым пропуская значение в каждой итерации. - Учтите также, что стандартная
list
функция уже имеет эту функцию создания списка из итератора. - В
find
функции вы ничего не делаете со значениями, полученными рекурсивным вызовом. Вы также должны уступить им. Для этого вы можете использоватьyield from
синтаксис. if not root
не будет работать корректно, когда дерево действительно пустое, так как выполнение все еще продолжается после этогоif
блока, и поэтому возникнет исключение. Тебе нужноreturn
туда.- Кроме того, когда дерево пустое, не должно быть ничего, что было бы получено. Итератору разрешено просто ничего не давать, что в этом случае уместно.
- Это не проблема, но поскольку у вас есть
if not root
базовый вариант, вам действительно не нужно проверятьNone
, прежде чем идти влево или вправо. Таким образом, этиif
условия могут быть удалены, и рекурсивные вызовы могут выполняться безоговорочно.
Вот исправленная версия:
def leaves_list(self): def find(root): if not root: return if not root.left and not root.right: yield root.data yield from find(root.left) yield from find(root.right) return list(find(self.root))
Комментарии:
1. Этот комментарий может быть лучше помещен в вопрос, поскольку это тема Спрашивающего.
2. Я частично так и сделал, но затем увидел полный список вопросов вашего ответа и подумал, что он тоже может туда вписаться.
Ответ №2:
# my attempt a = find(self.root) lst = [] for i in a: lst.append(i) return lst
Более короткая альтернатива:
# my attempt return list(find(self.root))