简体   繁体   中英

Python How to implement a recursive method of Binary Search Tree that returns a list that contains every node in this tree

If there's a tree example

Return form: [(depth 1, [ all items in depth 1]), (depth 2, [ all items in depth2]) ]

this method printitem_all_layers() should returns [ (1,[2] ) , ( 2,[1,3] ) ]

Though I wrote a recursive method, items_at_depth(self, d) that can return a list of items of a tree at depth d, so I know it is easy to implement the method printitem_all_layers() using items_at_depth(self, d) . But it is much lesser efficient, So I'm thinking how to make printitem_all_layers() recursive itself so that I don't need another recursive method

class BinarySearchTree:
    def __init__(self, root):
                if root is None:
        self._root = None
        self._left = None
        self._right = None
    else:
        self._root = root
        self._left = BinarySearchTree(None)
        self._right = BinarySearchTree(None)

    def is_empty(self):
        return self._root is None

    def items_at_depth(self, d):

    """Return a sorted list of all items in this BST at depth <d>.

    Precondition: d >= 1.
    @type self: BinarySearchTree
    @type d: int
    @rtype: list
    """
    lst = []
    if d - 1 >= 1 and not self._left.is_empty():
        lst.extend(self._left.items_at_depth(d-1))
    if d == 1 and not self.is_empty():
        lst.append(self._root)
    if d - 1 >= 1 and not self._right.is_empty():
        lst.extend(self._right.items_at_depth(d-1))

    return lst

and following one is what I did before with no recursion

    def printitem_all_layers(self):
    """Return a list of items in the tree, separated by level.

    @type self: BinarySearchTree
    @rtype: list[(int, list)]

    """
    lst = list()
    for each in range(1, self.height()+1):
        lst.append(tuple((each, self.items_at_depth(each))))
    return lst

What follows is an iterative version of breadth-first search, which is suitable for your problem, more efficient in terms of stack-space usage and guarantees similar runtime as a purely recursive implementation:

from collections import defaultdict

class Node:

    def __init__(self, value, descendants=[]):
        ''' A class to represent the node of a tree '''

        self.value = value

        # note that descendants should be iterable for 
        # our breadth-first search logic to take place
        # - otherwise it doesn't really matter what type 
        # it is.
        self.descendants = descendants

    def __repr__(self):
        return str(self.value)

def print_layer(root):

    # private queue consists of elements of the form (depth, Node)
    private_queue = [(0,root)]

    # instantiate a dictionary where every new value is always initialized 
    # to a list 
    depth_to_nodes_map = defaultdict(list)

    # keep adding descendants of each node in your tree to your queue
    # in order of visiting them, and also store each popped value in
    # your defaultdict, mapping depth to a list of nodes seen. Look up
    # breadth-first search if you don't understand why I'm waiting for
    # the queue to exhaust itself.

    while private_queue != []:

        # get the first element of private_queue
        current_depth, current_node = private_queue.pop(0)

        depth_to_nodes_map[current_depth].append(current_node)

        for child in current_node.descendants:
            private_queue.append((current_depth + 1, child))

    return depth_to_nodes_map.items()

An example with a reference tree:

2 -> {1 -> {0}, 3}

We would create this tree as follows:

root = Node(2, [Node(1, [Node(0)]), Node(3)])

and calling print_layers(root) gives:

[(0, [2]), (1, [1, 3]), (2, [0])]

which is exactly what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM