[英]Implementing recursive functions for trees in python class
我創建了一個類Tree
和一個Node
類。 現在我需要實現preOrder
, postOrder
和inOrder
遍歷。 我是用私人功能做的。 但有沒有辦法只使用一個函數來做同樣的事情?
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()
這里我必須使用輔助函數,因為我不希望用戶顯式提供根元素。
是的,您可以在單個函數中實現所有3種類型的遍歷。 我已經將遍歷函數轉換為生成器,以使它們更加通用。 因此,它們不是打印數據,而是生成數據的迭代器。 這使您可以在數據生成時處理數據,也可以將數據捕獲到列表(或其他集合)中。
在Python 2中,您的類應該繼承自object
,否則您將獲得舊式類,與新式類相比,它們相當有限(Python 3只有新式類)。
順便說一句,沒有必要為私有函數(調用Python的名稱修改機制)使用雙下划線,單個前導下划線就足夠了。
我還在類中添加了簡單的__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())
產量
('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']
以下是處理數據時的示例:
for data in tree.inOrder():
print data
FWIW,這段代碼在Python 3中會更加清晰,因為我們可以使用語法的yield from
而不是for
循環。 而不是
for u in self._traverse(root.left, mode):
yield u
我們能做到
yield from self._traverse(root.left, mode)
我不確定將遍歷函數實現為單行,但是您嘗試做的另一種方法是通過將遍歷邏輯抽象為一系列單獨的類來使策略模式適應您的用例。所有都繼承自一個常見的TraversalStrategy
。 然后,您可以將遍歷策略對象注入為Tree
的依賴項,從而將Tree
的結構與用於遍歷它的邏輯分離。
這種方法有以下好處:
Tree
方法的大部分 Tree
類現在具有單一職責 - 改變的一個原因 Tree
的源代碼,即它已關閉以進行修改 下面的代碼是為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()
產量
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.