0

For example, the binary search tree has an entry 5; it has two branches which left node entry is 2 and right is 7. Each node has two branches as well: for node entry 2, it has left node entry 1 and right node entry 3; for node entry 7, it has left node entry 6 and right node entry 10 and 8. To visit nodes' entries in the correct order, first visit the left branch([1,2] and then 3); then visit 5; finally visit the right branch(first[6,7] and then [8,10])

How to create a function "binary_tree(entry,left,right)" in order to get the tree abstract data output instead of using functions sorted or sort.? And how to define entry(tree), left_branch(tree) and right_branch(tree)?

1 Answers1

1

By definition, an abstract class is one you cannot directly instantiate; rather, you instantiate concrete classes (usually subclasses of the abstract one) implementing it.

So, define the programming interface you want for your abstract class: e.g, in Python 2 (it's a bit more elegant in Py 3, but equivalent):

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

and then one or more concrete subclasses, and use the latter.

For example:

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

Note that this is quite an anomalous case since the concrete class gets no functionality from that empty abstract class -- in real life, i.e except for didactic purposes, I would not use abstract classes for this case, as there's no added value in them here. Still, if you insist, this is how you do it:-).

Similarly for the auxiliary function you specify (here I'm switching to Py 3 as the elegance's irresistible):

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)

In real life, I'd make this a method of AbstractTree, not a free-standing function as you've required. Similarly for the other three auxiliary functions you specify, which exactly duplicate the getter methods of the abstract class...!

EDIT: apparently the adjective abstract is overloaded enough that the Q is not about Python's own abstract base classes, but a more, well, abstract (!) sense of the word "abstract". In that case, one might e.g map each tree node into a 3-items tuple (if tree nodes are immutable):

(entry, left, right)

still using None to represent "missing" left and right children; in that case, the accessor functions would obviously be

def entry(tree): return tree[0]
def left_branch(tree): return tree[1]
def right_branch(tree): return tree[2]

and the requested function that does an in-order walk on the tree would use a generator such as (going back to Py2-compatible code:-)...:

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

I'm still using a generator because it is so obviously the "only one right way to do it" for walking a tree (with the choice of what to do with each entry, whether printing it or otherwise, clearly belonging to a different function looping over this generator!). But I've switched to Py2-compatible loops of yield an_entry as that makes it trivial to replace each yield with a print if required by the homework.

I've changed the names from the Q's specs because the Q's specs are totally broken WRT naming -- they require that a local argument (the first one) be named entry but also the accessor function for the entry of a tree node be identically named entry -- causing a completely unnecessary naming conflict [*]. So I've kept the entry name only the for accessor function and switched to the_entry for argument name and an_entry for the other local variable needed in the for loops.

[*] it could be solved, e.g by using globals()['entry'] to access the shadowed global name, but it's just silly to put oneself deliberately in the position to have to reach for such "Hail Mary passes" when just using non-conflicting names in the first place is so much simpler!-)

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • I guess this is more about some SICP based programming course in Python where they need to do abstract data types instead of classes. – Antti Haapala -- Слава Україні Mar 21 '15 at 16:08
  • Yeah, I think the question just asks for basic ADT. – chrsitinav Mar 21 '15 at 16:35
  • @chrsitinav, there's really no such thing as a "basic ADT" in Python (while there **are** abstract **base classes** as part of the language!), but I've edited my answer to show one approach to dealing with what I think you mean, take a look. – Alex Martelli Mar 21 '15 at 16:59
  • @Alex Thanks for your clear explanation. I typed my code in python and tested it, but it couldn't run. (for example: print(entry(build_tree(1,2,3)))——1) – chrsitinav Mar 22 '15 at 03:19
  • @chrsitinav, this is the first time **ever** you mentioned a `build_tree` function...! Sorry, we're **not** mind-readers -- if you forget mentioning key specs and expect us to read your mind about them nevertheless, you **are** going to be sorely disappointed! What about **telling us** about *all* the specs, rather than expecting us to guess half of them or more -- too revolutionary a concept for you...?! – Alex Martelli Mar 22 '15 at 04:08