Trouble calling height() on a binary tree - python

I'm writing a function to check if a binary tree satisfies the Height-Balance Property. This is my code but I'm having trouble calling the height function for left and right from my given LinkedBinaryTree class. The main thing that's confusing me is that the nested function takes the root a parameter but height() doesn't. For reference, bin_tree is a LinkedBinaryTree() not a node. Thank you in advance for any help!
My Code
from LinkedBinaryTree import LinkedBinaryTree
def is_height_balanced(bin_tree):
if bin_tree.root is None:
return True
left = bin_tree.height()
right = bin_tree.height()
if abs(left - right) <= 1:
if is_height_balanced(bin_tree.root.left) is True and is_height_balanced(bin_tree.root.right) is True:
return True
return False
Portion of LinkedBinaryTree class
class LinkedBinaryTree:
class Node:
def __init__(self, data, left=None, right=None):
self.data = data
self.parent = None
self.left = left
if (self.left is not None):
self.left.parent = self
self.right = right
if (self.right is not None):
self.right.parent = self
def __init__(self, root=None):
self.root = root
self.size = self.count_nodes()
# assuming count_nodes() and is_empty() works as expected
def height(self):
def subtree_height(root):
if (root.left is None and root.right is None):
return 0
elif (root.left is None):
return 1 + subtree_height(root.right)
elif (root.right is None):
return 1 + subtree_height(root.left)
else:
left_height = subtree_height(root.left)
right_height = subtree_height(root.right)
return 1 + max(left_height, right_height)
if(self.is_empty()):
raise Exception("Tree is empty")
return subtree_height(self.root)

Related

binary search tree missing 1 required positional argument:

Trying to construct the Binary search tree here
class Node:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BSTree():
def __init__(self, rootdata):
self.root = Node(rootdata)
def insert(self, data, cur_node):
if data < cur_node.data:
if cur_node.left == None:
cur_node.left = Node(data)
else:
self.insert(data, cur_node.left)
elif data > cur_node.data:
if cur_node.right == None:
cur_node.right = Node(data)
else:
self.insert(data, cur_node.right)
else:
print("Duplicate value!")
def find(self, data, cur_node):
if data < cur_node.data and cur_node.left:
return self.find(data, cur_node.left)
elif data > cur_node.data and cur_node.right:
return self.find(data, cur_node.right)
if data == cur_node.data:
return True
return False
def PreOder(self,root):
if root == None:
pass
else:
print(root.data)
self.PreOrder(root.left)
self.PreOrder(root.right)
a = BSTree()
a.insert(3)
a.insert(4)
a.insert(7)
a.insert(34)
a.insert(24)
a.insert(2)
a.insert(49)
print(a.find(3))
print(a.PreOrder(3))
I am getting an error message: init() missing 1 required positional argument: 'rootdata'
How to fix and print the binary search tree?
Also, what I have up there is just the random number I am try to construct the binary tree out from the list I have
mylist = [1,3,2,4,12,14,23,43,23,44,34,43]
Here is a working and properly formatted update of your code. Not sure what it's doing exactly, but it should give you some clues to solve your task. Maybe you could use an IDE like Visual Studio Code or Pycharm to help you out with python specific stuff.
class Node:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BSTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def insert(self, data, cur_node):
if data < cur_node.data:
if cur_node.left is None:
cur_node.left = Node(data)
else:
self.insert(data, cur_node.left)
elif data > cur_node.data:
if cur_node.right is None:
cur_node.right = Node(data)
else:
self.insert(data, cur_node.right)
else:
print("Duplicate value!")
def find(self, data, cur_node):
if data < cur_node.data and cur_node.left:
return self.find(data, cur_node.left)
elif data > cur_node.data and cur_node.right:
return self.find(data, cur_node.right)
if data == cur_node.data:
return True
return False
def pre_order(self, root):
if root is None:
pass
else:
print(root.data)
self.pre_order(root.left)
self.pre_order(root.right)
a = BSTree(3)
a.insert(4, a.root)
a.insert(7, a.root)
a.insert(34, a.root)
a.insert(24, a.root)
a.insert(2, a.root)
a.insert(49, a.root)
print(a.find(3, a.root),)
print(a.pre_order(a.root))
Some issues:
Your BSTree constructor does not create an emtpy tree, but a tree with already one node, and so it expects the data for that node as argument. This design is not good, because it does not support the concept of an empty tree. So the constructor should change and just set self.root to None.
insert takes also more arguments than expected: it does so because it uses that argument for implementing recursion. There are many ways to make it work, but I prefer that the recursive call is made in OOP-style, i.e. the recursive insert method should be placed in the Node class, and act on self instead of on an extra argument. The insert method on the BSTree class can then just be a wrapper around that method, where it gets called on the root node.
A similar issue occurs with find. The solution can be the same as for insert.
And again, the issue occurs also with preOrder: it takes a node as argument. Same solution as discussed above. I would also avoid printing in a method. Instead yield the values.
So here is how that would look:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def insert(self, data):
if data < self.data:
if not self.left:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if not self.right:
self.right = Node(data)
else:
self.right.insert(data)
else:
print("Duplicate value!")
def find(self, data):
if data < self.data and self.left:
return self.left.find(data)
elif data > self.data and self.right:
return self.right.find(data)
return data == self.data
def preOrder(self):
yield self.data
if self.left:
yield from self.left.preOrder()
if self.right:
yield from self.right.preOrder()
class BSTree():
def __init__(self):
self.root = None
def insert(self, data):
if not self.root:
self.root = Node(data)
else:
self.root.insert(data)
def find(self, data):
return self.root.find(data) if self.root else False
def preOrder(self):
if self.root:
yield from self.root.preOrder()
a = BSTree()
a.insert(3)
a.insert(4)
a.insert(7)
a.insert(34)
a.insert(24)
a.insert(2)
a.insert(49)
print(a.find(3))
print(*a.preOrder()) # With * we splash every yielded value as argument to print().

How to find if a value exist within a Binary Tree: True or False (Python3)

I am trying to write a code which the output returns either True or False, if the value exists within the Binary Tree.
Here is my attempt:
Defining a class called Node:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
Defining a class called BinaryTree + LOOKUP function:
class BinaryTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def LOOKUP(self, lookupval):
if lookupval < self.data:
if (self.left == None):
self.left.LOOKUP(lookupval)
return False
elif lookupval > self.data:
if (self.right == None):
self.right.LOOKUP(lookupval)
return False
else:
return True
The rest, inputting values into the Binary Tree:
Tree = BinaryTree(24)
Tree.root.left = Node(11)
Tree.root.left.left = Node(199)
Tree.root.left.right = Node(167)
Tree.root.right = Node(2)
Tree.root.right.right = Node(8)
print(Tree.LOOKUP(11))
print(Tree.LOOKUP(13))
However, I keep getting the error 'BinaryTree' object has no attribute 'data'..
I understand there will be some errors in the definition of the function LOOKUP,
but is there any chance that I could keep this format and still return the outputs:
True
False
Thank you,
The issues in your code are:
you're trying to reference self.right (should be self.root.right instead - because we're not on the Node instance)
the nested if check are wrong. You should recursively check the left/right tree if NOT None or return False there.
Do something like this:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BinaryTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def LOOKUP(self, lookupval):
if lookupval < self.root.data:
if self.root.left:
return BinaryTree(self.root.left.data).LOOKUP(lookupval) # recursively check the left tree
else:
return False # can't go any further- so return false
elif lookupval > self.root.data:
if self.root.right:
return BinaryTree(self.root.right.data).LOOKUP(lookupval)
else:
return False
else:
return True
Tree = BinaryTree(24)
Tree.root.left = Node(11)
Tree.root.left.left = Node(199)
Tree.root.left.right = Node(167)
Tree.root.right = Node(2)
Tree.root.right.right = Node(8)
print(Tree.LOOKUP(11))
print(Tree.LOOKUP(13))
output:
True
False

How to get the length of a tree in python binary search

class Node:
def __init__(self,data=None):
self.data=data
self.left_child=None
self.right_child=None
self.parent=None
self.root = None
class BinarySearchTree:
def __init__(self):
self.root=None
def add(self, data):
if self.root == None:
self.root = Node(data)
else:
self.add_helper(data, self.root)
def add_helper(self, data, cur_node):
if data < cur_node.data:
if cur_node.left_child == None:
cur_node.left_child = Node(data)
cur_node.left_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.left_child)
elif data > cur_node.data:
if cur_node.right_child == None:
cur_node.right_child = Node(data)
cur_node.right_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.right_child)
else:
print("data already in tree!")
def __len__(self):
if self.root is None:
return 0
else:
return (self.__len__(self.left_child) + 1 +self. __len__(self.right_child))
So i am trying to return the length of the binary search tree list, so i tried using the len method for my binary search tree class. However, this is not working correctly. I need it to be able to not take in any parameters, and just return an integer for the length of the binary search tree list. What am i missing and what am i doing wrong here?
You will need a helper function that takes a Node argument. Then do the recursion on the left and right of the node.
def __len__(self):
return self.tree_len(self.root)
def tree_len(self, node):
if node is None:
return 0
else:
return 1 + max(self.tree_len(node.right_child), self.tree_len(node.left_child))

Binary search tree insert method not working

class Node:
def __init__(self,value = None):
self.value = value
self.left = None
self.right = None
class binary_search_tree:
def __init__(self):
self.root = None
def insert(self,current,value):
if current == None:
current = Node(value)
elif value < current.value:
self.insert(current.left,value)
elif value > current.value:
self.insert(current.right,value)
tree = binary_search_tree()
for i in (12,5,18,3,4,6):
tree.insert(tree.root,i)
The insert method for my binary search tree is not working can someone help me out.
(Post is mostly code, please add more details.)

'NoneType' object has no attribute 'height'

I am trying to find the height of a BST but it is giving error like 'NoneType' object has no attribute 'height'. I can't figure out the error.
class BST:
def __init__(self,val):
self.left = None
self.right = None
self.root = val
def insert(self,data):
if self.root == None:
self.root = BST(data)
elif data > self.root:
if self.right == None:
self.right = BST(data)
else:
self.right.insert(data)
elif data < self.root:
if self.left == None:
self.left = BST(data)
else:
self.left.insert(data)
def inorder(self):
if self.left != None:
self.left.inorder()
print(self.root)
if self.right != None:
self.right.inorder()
def height(self):
if self.root == None:
return 0
else:
return 1 + max(self.left.height(), self.right.height())
t = BST(4)
t.insert(1)
t.insert(7)
t.insert(3)
t.insert(6)
t.insert(2)
t.insert(5)
t.inorder()
print(t.height())
You need to change your init method to be this:
def __init__(self,val):
self.left = None
self.right = None
self.root = val
self.rheight = 0
self.lheight = 0
And your height method to be this:
def height(self):
if self.root == None:
return 0
else:
if hasattr(self.left, 'height'):
self.lheight = self.left.height()
if hasattr(self.right, 'height'):
self.rheight = self.right.height()
return 1 + max(self.lheight, self.rheight)
The reason this needs to change is, you are calling height all the way down your tree, thus getting all the way to None on the right and left sides, all the way at the bottom of the tree. So what this does is check if self.right and self.left have the attribute of height. They won’t if the type is None, so when both are None, we return all the way back out.
When you get to this line
return 1 + max(self.left.height(), self.right.height())
Then at some point, self.left becomes not defined (though not at the very start). You can check this by adding print(self.left) just before that statement, and you will see None outputted just before the error message.
This means that while self.root is defined, your base case needs to includes self.left (and possibly self.right), so that at no point are any of those None.
Replace this line:
return 1 + max(self.left.height(), self.right.height())
with
if hasattr(self.left, 'height'):
left_height = self.left.height()
if hasattr(self.right, 'height'):
right_height = self.right.height()
return 1 + max(left_height, right_height)

Categories