Search code examples
pythonbinary-search-treenodesnonetypepython-class

How to fix NoneType error in Python Binary Search Tree?


I'm creating a basic binary search tree program where the nodes have to be strings however, I keep getting this error: 'builtins.AttributeError: 'NoneType' object has no attribute 'addNode'

I'm a bit confused because I thought you had to declare the children nodes as None. My code is below (please excuse the messiness and extra print statements):

class BinarySearchTree:
  #constructor with insertion value & left/right nodes as None
  def __init__(self, data):
    self.data = data
    self.left = None
    self.right = None
  
  #function to insert node
  def addNode(root, data):
    #when tree doesn't exist
    if root == None:
      return BinarySearchTree(data)
    else:
      #when node is already in tree
      if root.data == data:
        return root
      #smaller values go left
      elif data < root.data:
          root.left.addNode(data)
      #bigger values go right
      else:
          root.right.addNode(data)
    return root

  #function to find smallest node value (to help with deletion)  
  def smallestNode(root):
      node = root
      #loop goes to lowest left leaf
      while(node.left is not None):
          node = node.left
      return node

  #function to delete node
  def removeNode(root, data):
    if root == None:
      return root
    #when node to be deleted in smaller than root, go left
    if data < root.data:
      root.left = root.left.removeNode(data)
    #when node to be deleted in bigger than root, go right
    elif data > root.data:
        root.right = root.right.removeNode(data)
    ##when node to be deleted in the same as root...
    else:
        #when node has only 1 or 0 children
        if root.right == None:
            move = root.left
            root = None
            return move
        elif root.left == None:
            move = root.right
            root = None
            return move
        #when node has 2 children, copy then delete smallest node
        move = root.right.smallestNode()
        root.data = move.data
        root.right = root.right.removeNode(move.data)
    return root

  def findNode(root, data):
    #if current node is equal to data value then return the root
    if root.data == data or root == None:
      return root
    #if current node is greater than the data value then, search to the left
    elif data < root.data:
      return root.left.findNode(data)
    #if current node is less than the data value then, search to the right
    else:
      return root.right.findNode(data)

def createBST(keys):
  root = BinarySearchTree(keys[0])

  for i in range(1,len(keys)):
      root.addNode(keys[i])
  return root

print('Hi! Welcome to the Binary Search Tree Builder')
print('Here are your options below:')
print('1) Build new tree')
print('2) Add a node')
print('3) Find a node')
print('4) Delete a node')
choice = int(input('What would you like to do?: '))
if choice == 1:
  nodes = list(input("Enter the strings you would like to build your tree from (separate by a space): ").split())
  print(nodes)
  tree = createBST(nodes)
  print(tree)

I'm wondering where exactly is this error coming from and how can I fix it? Also, if you see any other problems occuring in my code, please let me know!


Solution

  • You have conflated the notion of "tree node" and "tree". What you have there is a mixture of the two. Remember, the first parameter to ALL member functions should be "self". Replacing "root" by "self" might make your problem more clear.

    So, you might create a BinaryTree class, which has a single member called self.root that holds a BinaryTreeNode object, once you have a node. The nodes will hold the left and right values, each of which will either have None or a BinaryTreeNode object. The node class probably doesn't need much code -- just self.left and self.right.

    The BinaryTree class will have an addNode member that knows how to traverse the tree to find the right spot, but when you find the spot, you just set self.left = BinaryTreeNode(...). A node does not know about the tree, so a node does not know how to add new nodes. That's a function of the tree itself.

    Does that make your path forward more clear?