Skip to content Skip to sidebar Skip to footer

Yield All Root-to-leaf Branches Of A Binary Tree

Sorry if this is a common question but I haven't found an appropriate answer for my particular problem. I'm trying to implement a walk method that walks a binary tree from its root

Solution 1:

Here's a modified variant of your code.

code.py:

#!/usr/bin/env python3import sys


classNode:
    def__init__(self, data=None, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

    def__repr__(self):
        returnf"{self.__class__.__name__}({self.data})"    @propertydefchildren(self):
        if self.left:
            yield self.left
        if self.right:
            yield self.right

    @propertydefis_leaf(self):
        return self.left isNoneand self.right isNonedeftraverse_preord(self, accumulator=list()):
        print("  On node:", self)
        accumulator.append(self.data)
        if self.is_leaf:
            yield accumulator
        else:
            for child in self.children:
                print("  Entering child:", child)
                yieldfrom child.traverse_preord(accumulator=accumulator)
                accumulator.pop()
                print("  Exiting child:", child)


defmain():
    root = Node(data="A",
                left=Node(data="B",
                          right=Node(data="C")
                         ),
                right=Node(data="D",
                           #left=Node(data="E"),#right=Node(data="F"),
                          )
               )
    for path in root.traverse_preord():
        print("Found path:", path)


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Notes:

  • I refactored the code a bit (simplified, changed some identifier names, texts and other insignificant changes)
  • children property:
    • None for a node's left or right attribute, means that the node has no child, so no point including it in the returned result
    • Since the question is involving yield, I turned it into a generator (instead of returning a tuple or list, ...). As a consequence, I had to add is_leaf, since a generator doesn't evaluate to False (even if empty)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q055424449]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32

  On node: Node(A)
  Entering child: Node(B)
  On node: Node(B)
  Entering child: Node(C)
  On node: Node(C)
Found path: ['A', 'B', 'C']
  Exiting child: Node(C)
  Exiting child: Node(B)
  Entering child: Node(D)
  On node: Node(D)
Found path: ['A', 'D']
  Exiting child: Node(D)

What is wrong with your code?

It's the traverse recurring call (child.traverse(branch=branch)). It created a generator, but since that wasn't used (iterated on) anywhere, the function didn't actually called itself, resulting in the attempt of removing more elements than added (only 1: which is the root node). So, it turns out that you were almost there. All you have to do, is adding a yield from in front of it :). More details on [Python]: PEP 380 -- Syntax for Delegating to a Subgenerator.

Solution 2:

There is a great answer here

Copying their Python example:

""" 
Python program to print all path from root to 
leaf in a binary tree 
"""# binary tree node contains data field ,  # left and right pointer classNode: 
    # constructor to create tree node def__init__(self, data): 
        self.data = data 
        self.left = None
        self.right = None# function to print all path from root # to leaf in binary tree defprintPaths(root): 
    # list to store path 
    path = [] 
    printPathsRec(root, path, 0) 

# Helper function to print path from root  # to leaf in binary tree defprintPathsRec(root, path, pathLen): 

    # Base condition - if binary tree is # empty return if root isNone: 
        return# add current root's data into  # path_ar list # if length of list is gre if(len(path) > pathLen):  
        path[pathLen] = root.data 
    else: 
        path.append(root.data) 

    # increment pathLen by 1 
    pathLen = pathLen + 1if root.left isNoneand root.right isNone: 

        # leaf node then print the list 
        printArray(path, pathLen) 
    else: 
        # try for left and right subtree 
        printPathsRec(root.left, path, pathLen) 
        printPathsRec(root.right, path, pathLen) 

# Helper function to print list in which  # root-to-leaf path is stored defprintArray(ints, len): 
    for i in ints[0 : len]: 
        print(i," ",end="") 
    print() 

# Driver program to test above function """ 
Constructed binary tree is  
      10 
    /   \ 
   8     2 
  / \   / 
 3   5 2 
"""
root = Node(10) 
root.left = Node(8) 
root.right = Node(2) 
root.left.left = Node(3) 
root.left.right = Node(5) 
root.right.left = Node(2) 
printPaths(root) 

# This code has been contributed by Shweta Singh. 

Gives:

10 8 3 10 8 5 10 2 2

You can give it letters like you have too:

root = Node("A") 
root.left = Node("B") 
root.right = Node("D") 
root.left.right = Node("C") 
printPaths(root) 

Gives:

A B C A D

Post a Comment for "Yield All Root-to-leaf Branches Of A Binary Tree"