[英]Implementing recursive functions for trees in python class
I have created a class Tree
and a class Node
. 我创建了一个类Tree
和一个Node
类。 Now I needed to implement preOrder
, postOrder
and inOrder
traversals. 现在我需要实现preOrder
, postOrder
和inOrder
遍历。 I did it using private functions. 我是用私人功能做的。 But is there a way to do the same using only one function? 但有没有办法只使用一个函数来做同样的事情?
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
class Tree:
def __init__(self):
self.root = None
# Private helper functions
def __insert(self, data, root):
if data < root.data:
if root.left is None:
root.left = Node(data)
else:
self.__insert(data, root.left)
elif data >= root.data:
if root.right is None:
root.right = Node(data)
else:
self.__insert(data, root.right)
# Traversals
def __preOrder(self, root):
print root.data
if root.left:
self.__preOrder(root.left)
if root.right:
self.__preOrder(root.right)
# Wrapper Functions
def insert(self, data):
if self.root == None:
self.root = Node(data)
else:
self.__insert(data, self.root)
def preOrder(self):
self.__preOrder(self.root)
tree = Tree()
print "Enter elements to be inserted in the tree(End with a -1): "
while True:
elem = int(raw_input())
if elem == -1:
break
tree.insert(elem)
print "Preorder traversal: "
tree.preOrder()
Here I have to use the helper functions because I don't want the user to be providing the root element explicitly. 这里我必须使用辅助函数,因为我不希望用户显式提供根元素。
Yes, you can implement all 3 types of traversal in a single function. 是的,您可以在单个函数中实现所有3种类型的遍历。 I've turned the traversal functions into generators to make them more versatile. 我已经将遍历函数转换为生成器,以使它们更加通用。 So instead of printing their data they are iterators that yield their data. 因此,它们不是打印数据,而是生成数据的迭代器。 This lets you process the data as it's yielded, or you can capture it into a list (or other collection). 这使您可以在数据生成时处理数据,也可以将数据捕获到列表(或其他集合)中。
In Python 2 your classes should inherit from object
, otherwise you get old-style classes, which are rather limited compared to new-style classes (Python 3 only has new-style classes). 在Python 2中,您的类应该继承自object
,否则您将获得旧式类,与新式类相比,它们相当有限(Python 3只有新式类)。
BTW, there's no need to use double underscores for the private functions (which invokes Python's name-mangling machinery), a single leading underscore is adequate. 顺便说一句,没有必要为私有函数(调用Python的名称修改机制)使用双下划线,单个前导下划线就足够了。
I've also added simple __repr__
methods to the classes, which can be handy during development & debugging. 我还在类中添加了简单的__repr__
方法,这在开发和调试过程中非常方便。
class Node(object):
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def __repr__(self):
return repr((self.data, self.left, self.right))
class Tree(object):
def __init__(self):
self.root = None
def __repr__(self):
return repr(self.root)
# Private helper functions
def _insert(self, data, root):
if data < root.data:
if root.left is None:
root.left = Node(data)
else:
self._insert(data, root.left)
else: # data >= root.data:
if root.right is None:
root.right = Node(data)
else:
self._insert(data, root.right)
def _traverse(self, root, mode):
if mode == 'pre':
yield root.data
if root.left:
for u in self._traverse(root.left, mode):
yield u
if mode == 'in':
yield root.data
if root.right:
for u in self._traverse(root.right, mode):
yield u
if mode == 'post':
yield root.data
# Wrapper Functions
def insert(self, data):
if self.root == None:
self.root = Node(data)
else:
self._insert(data, self.root)
def preOrder(self):
for u in self._traverse(self.root, 'pre'):
yield u
def inOrder(self):
for u in self._traverse(self.root, 'in'):
yield u
def postOrder(self):
for u in self._traverse(self.root, 'post'):
yield u
# Test
tree = Tree()
for elem in '31415926':
tree.insert(elem)
print tree
print "Preorder traversal: "
print list(tree.preOrder())
print "InOrder Traversal: "
print list(tree.inOrder())
print "PostOrder Traversal: "
print list(tree.postOrder())
output 产量
('3', ('1', None, ('1', None, ('2', None, None))), ('4', None, ('5', None, ('9', ('6', None, None), None))))
Preorder traversal:
['3', '1', '1', '2', '4', '5', '9', '6']
InOrder Traversal:
['1', '1', '2', '3', '4', '5', '6', '9']
PostOrder Traversal:
['2', '1', '1', '6', '9', '5', '4', '3']
Here's an example of processing the data as it's yielded: 以下是处理数据时的示例:
for data in tree.inOrder():
print data
FWIW, this code would be a lot cleaner in Python 3 because we could use the yield from
syntax instead of those for
loops. FWIW,这段代码在Python 3中会更加清晰,因为我们可以使用语法的yield from
而不是for
循环。 So instead of 而不是
for u in self._traverse(root.left, mode):
yield u
we could do 我们能做到
yield from self._traverse(root.left, mode)
I'm not sure about implementing the traversal functions as one-liners, but an alternative approach to what you're trying to do would be to adapt the Strategy Pattern to your use case by abstracting the traversal logic into a series of separate classes that all inherit from one common TraversalStrategy
. 我不确定将遍历函数实现为单行,但是您尝试做的另一种方法是通过将遍历逻辑抽象为一系列单独的类来使策略模式适应您的用例。所有都继承自一个常见的TraversalStrategy
。 You can then inject a traversal strategy object as a dependency to Tree
which decouples the structure of the tree from the logic used to traverse it. 然后,您可以将遍历策略对象注入为Tree
的依赖项,从而将Tree
的结构与用于遍历它的逻辑分离。
This approach has the following benefits: 这种方法有以下好处:
Tree
methods 它允许您摆脱当前Tree
方法的大部分 Tree
class now has a Single Responsibility - a single reason to change 您的Tree
类现在具有单一职责 - 改变的一个原因 Tree
ie it's closed for modification 您可以为树实现新的遍历行为,而无需触及Tree
的源代码,即它已关闭以进行修改 The code below has been written for Python 3, so it will need some minor changes to work for Python 2. 下面的代码是为Python 3编写的,因此需要对Python 2进行一些小的更改。
from abc import ABC, abstractmethod
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def __repr__(self):
return str(self.data)
class Tree:
def __init__(self, traversal_strategy):
self.root = None
self.traversal_strategy = traversal_strategy
def insert(self, data):
if self.root is None:
self.root = Node(data)
else:
self.__insert(data, self.root)
def __insert(self, data, root):
if data < root.data:
if root.left is None:
root.left = Node(data)
else:
self.__insert(data, root.left)
elif data >= root.data:
if root.right is None:
root.right = Node(data)
else:
self.__insert(data, root.right)
def traverse(self):
self.traversal_strategy.traverse(self.root)
class TraversalStrategy(ABC):
@abstractmethod
def traverse(self, node):
pass
def _attempt_traverse(self, node):
if node:
self.traverse(node)
class PreOrderTraversal(TraversalStrategy):
def traverse(self, node):
print(node)
self._attempt_traverse(node.left)
self._attempt_traverse(node.right)
class InOrderTraversal(TraversalStrategy):
def traverse(self, node):
self._attempt_traverse(node.left)
print(node)
self._attempt_traverse(node.right)
class PostOrderTraversal(TraversalStrategy):
def traverse(self, node):
self._attempt_traverse(node.left)
self._attempt_traverse(node.right)
print(node)
def build_tree(traversal_strategy):
tree = Tree(traversal_strategy)
elements = [1, 3, 6, 9, 2, 8]
for element in elements:
tree.insert(element)
return tree
if __name__ == '__main__':
pre_order_tree = build_tree(PreOrderTraversal())
in_order_tree = build_tree(InOrderTraversal())
post_order_tree = build_tree(PostOrderTraversal())
print('Pre order traversal: ')
pre_order_tree.traverse()
print()
print('In order traversal: ')
in_order_tree.traverse()
print()
print('Post order traversal: ')
post_order_tree.traverse()
print()
Output 产量
Pre order traversal:
1
3
2
6
9
8
In order traversal:
1
2
3
6
8
9
Post order traversal:
2
8
9
6
3
1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.