例如,二叉搜索树有一个条目5;它有两个分支,其中节点条目为2,右边为7.每个节点也有两个分支:对于节点条目2,它有左节点条目1和右节点条目3;对于节点入口7,它已经离开节点入口6和右节点入口10和8.要访问节点'输入顺序正确,首先访问左分支([1,2]然后3);然后访问5;最后访问右分支(第[6,7],然后[8,10])
如何创建一个函数" binary_tree(entry,left,right)"为了获取树抽象数据输出而不是使用排序或排序的函数。以及如何定义条目(树),left_branch(树)和right_branch(树)?
答案 0 :(得分:1)
根据定义,抽象类是您无法直接实例化的类;相反,你实例化具体的类(通常是抽象的类的子类)来实现它。
所以,为你的抽象类定义你想要的编程接口:例如,在Python 2中(它在Py 3中更优雅,但是相当于):
import abc
class AbstractTree(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def entry(self): return
@abc.abstractmethod
def left(self): return
@abc.abstractmethod
def right(self): return
然后是一个或多个具体的子类,并使用后者。
例如:
class SimpleTree(AbstractTree):
def __init__(self, entry, left=None, right=None):
self.entry = entry
self.left = left
self.right = right
def entry(self): return self.entry
def left(self): return self.left
def right(self): return self.right
请注意,这是一个非常异常的情况,因为具体类没有从空的抽象类中获取任何功能 - 在现实生活中,即除了教学目的之外,我会不使用抽象类来实现这一点因为这里没有附加值。不过,如果你坚持,你就是这样做的: - )。
与你指定的辅助功能类似(这里我转换为Py 3,因为优雅不可抗拒):
def binary_tree_generator(entry, left, right):
if left is not None:
yield from binary_tree_generator(left.entry, left.left, left.right)
yield entry
if right is not None:
yield from binary_tree_generator(right.entry, right.left, right.right)
def binary_tree(entry, left, right):
for anentry in binary_tree_generator(entry, left, right):
print(anentry)
在现实生活中,我会将其作为AbstractTree的一种方法,不这是您所需要的独立功能。类似地,对于您指定的其他三个辅助函数,它们完全复制抽象类的getter方法......!
编辑:显然,形容词 abstract 已经超载,以至于Q 不关于Python自己的抽象基类,但更多,更好,抽象(!)感觉“抽象”这个词。在这种情况下,可以例如将每个树节点映射到3项元组(如果树节点是不可变的):
(entry, left, right)
仍然使用None
代表“失踪”left
和right
个孩子;在这种情况下,访问器功能显然是
def entry(tree): return tree[0]
def left_branch(tree): return tree[1]
def right_branch(tree): return tree[2]
并且在树上执行有序遍历的请求函数将使用生成器,例如(返回与Py2兼容的代码: - )...:
def binary_tree_generator(the_entry, left, right):
if left is not None:
for an_entry in binary_tree_generator(
entry(left), left_branch(left), right_branch(left)):
yield an_entry
yield the_entry
if right is not None:
for an_entry in binary_tree_generator(
entry(right), left_branch(right), right_branch(right)):
yield an_entry
我仍在使用生成器,因为它显然是“走树”的唯一正确方法(可以选择如何处理每个条目,无论是print
还是yield an_entry
否则,显然属于循环在这个发生器上的不同功能!)。但是我已经切换到yield
的Py2兼容循环,因为如果家庭作业需要,用print
替换每个entry
会很容易。
我已经从Q的规格中更改了名称,因为Q的规格完全被破坏了WRT命名 - 它们要求本地参数(第一个)被命名为entry
但也用于输入树节点的访问器函数相同命名为entry
- 导致完全不必要的命名冲突[*]。所以我只将the_entry
名称保留为访问者函数,并将an_entry
替换为参数名称,并将for
替换为globals()['entry']
循环中所需的其他局部变量。< / p>
[*]它可以被解决,例如通过使用{{1}}来访问阴影的全局名称,但是只是愚蠢地把自己故意放在必须达到这样的“冰雹玛丽传递”的位置首先使用非冲突的名称要简单得多! - )