Я пытаюсь удалить все поддеревья, содержащие только нули. Мой код ниже. В настоящий момент запуск removeFailures на корневом узле вообще не изменяет дерево (выполнение обхода предварительного заказа до и после дает тот же результат).
Я думаю, что это потому, что когда я говорю "root is None", я на самом деле не модифицирую root, я просто могу создать имя переменной temp, возможно, корень? Если это так, как я могу это исправить? Не будет ли это рассуждение работать на Java?
# Ex.
# 4 4
# / \ / \
# 1 3 1 3
# / \ / \ --> / / \
# 0 0 4 6 0 4 6
# /\ /\ / \
# 3 5 0 0 3 5
class TreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def removeFailures(root):
if root is None:
return True
removeLeft = removeFailures(root.left)
removeRight = removeFailures(root.right)
if root.data == 0 and removeLeft and removeRight:
root = None
return True
return False
def preorder(root):
print root.data
if root.left:
preorder(root.left)
if root.right:
preorder(root.right)
example = TreeNode(4)
example.left = TreeNode(1, TreeNode(0, TreeNode(3), TreeNode(5)), TreeNode(0, TreeNode(0), TreeNode(0)))
example.right = TreeNode(3, TreeNode(4), TreeNode(6))
preorder(example)
print '*************************'
removeFailures(example)
preorder(example) #TODO
Чтобы проверить, что все узлы в дереве содержат нуль, вам придется перебирать каждый из этих узлов. Возможность создать метод __iter__
чтобы найти все узлы в дереве, а затем any
встроенную функцию можно применить, чтобы определить, все ли они равны нулю. Наконец, простой рекурсивный метод может проверять детей влево и вправо и при необходимости удалять.
Для простоты создания дерева kwargs
используется для создания структуры на месте без реализации метода rotate или длинной последовательности операторов присваивания:
class Tree:
def __init__(self, **kwargs):
self.__dict__ = {i:kwargs.get(i) for i in ['left', 'right', 'val']}
def __iter__(self):
yield self.val
yield from ([] if self.left is None else self.left)
yield from ([] if self.right is None else self.right)
@staticmethod
def remove_empty_trees(_t):
if not any(_t):
return None
_t.remove_trees()
return _t
def remove_trees(self):
if not any([] if self.left is None else self.left):
self.left = None
else:
self.left.remove_trees()
if not any([] if self.right is None else self.right):
self.right = None
else:
self.right.remove_trees()
# 4
# / \
# 1 3
# / \ / \
# 0 0 4 6
# /\ /\
# 3 5 0 0
t = Tree(val=4, left=Tree(val=1, left=Tree(val=0, left=Tree(val=3), right=Tree(val=5)), right=Tree(val=0, left=Tree(val=0), right=Tree(val=0))), right=Tree(val=3, left=Tree(val=4), right=Tree(val=6)))
new_tree = Tree.remove_empty_trees(t)
print(print(new_tree.left.right))
Выход:
None
Чтобы обработать случай, когда все дерево содержит узлы нуля, staticmethod
обеспечивает дополнительную проверку.
После рекурсивного вызова removeFailures()
на дочерних узлах необходимо установить для них None
если они были успешно удалены:
def removeFailures(root):
if root is None:
return True
removeLeft = removeFailures(root.left)
removeRight = removeFailures(root.right)
# Check if successfully removed children
if removeLeft:
root.left = None
if removeRight:
root.right = None
if root.data == 0 and removeLeft and removeRight:
root = None
return True
return False
Выход:
4
1
0
3
5
0
0
0
3
4
6
*************************
4
1
0
3
5
3
4
6
Установка самого узла на None
- недостаточно, потому что родительский узел все еще содержит ссылку на него. Поэтому необходимо установить все ссылки на этот узел на " None
чтобы правильно удалить его.