pythonrecursionbinary-treenodes

Recursive insert method on Binary Tree reaches the correct node but it doesn't save data


I'm trying to make a recursive insert method on a binary tree and while the recursive part of the function seems to do the job correctly (I tracked the code step by step with debug option) when time comes for data to be saved it just doesn't happen. Is it a reference mistake?

class TreeNode:
    def __init__(self, data=None, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

class BTree():
    def __init__(self, root=None):
        self.root = root

    def insert(self, data):

        def in_insert(node, data):
            if node is None:
                node = TreeNode(data)
            elif node.data == data:
                print(f'{node.data} already in here.')
            elif node.data > data:
                node = node.left
                in_insert(node, data)`
            else:
                node = node.right
                in_insert(node, data)

        if self.root is None:
            self.root = TreeNode(data)
        else:
            in_insert(self.root, data)

Solution

  • You are expecting this line node = TreeNode(data) to insert into the tree. But it's simply creating a node within the scope of the function that isn't being referenced by any other node's left or right.

    The fix would be

    class BTree():
        def __init__(self, root=None):
            self.root = root
    
        def insert(self, data):
            def in_insert(node, data):
                if node is None:
                    return TreeNode(data)
                elif node.data == data:
                    print(f'{node.data} already in here.')
                elif node.data > data:
                    node.left = in_insert(node.left, data)
                else:
                    node.right = in_insert(node.right, data)
                return node
    
            if self.root is None:
                self.root = TreeNode(data)
            else:
                self.root = in_insert(self.root, data)
    

    The changes are:

    But what is problematic with this is that it unnecessarily assigns the left or right references of all the nodes involved in the path to the added node. To optimise it, you could pass the parent node to the in_insert function to update the parent's left or right only at the point of insertion. Like so

    class BTree():
        def __init__(self, root=None):
            self.root = root
    
        def insert(self, data):
    
            def in_insert(node, parent, is_left, data):
                if node is None:
                    # We have found the point of insertion, time to create and insert
                    if is_left:
                        parent.left = TreeNode(data)
                    else:
                        parent.right = TreeNode(data)
                elif node.data == data:
                    print(f'{node.data} already in here.')
                elif node.data > data:
                    in_insert(node.left, node, True, data)
                else:
                    in_insert(node.right, node, False, data)
    
            if self.root is None:
                self.root = TreeNode(data)
            else:
                in_insert(self.root, None, None, data)