So I'm fairly new to programming and I am trying to make my delete function in my binary search tree to delete on the side that has the highest depth of nodes. However, I keep getting an error once I try to run it and I know it is a simple fix but I cannot figure it out after reading a few similar questions on here.
Here is my error I get:
C:\Python33\python.exe "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter7/Test.py"
Traceback (most recent call last):
File "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter7/Test.py", line 10, in <module>
a.delete(tree, 9)
File "C:\Users\koopt_000\Desktop\College\Sophomore Semester 2\Computer Science 231\Chapter7\BinarySearchTree.py", line 111, in delete
ldepth == max(self.height(root.left))
TypeError: 'int' object is not iterable
Process finished with exit code 1
Here are my following parts of code starting from my TreeNodes, to BST(main function), and then my test code.
class TreeNode(object):
def __init__(self, data = None, left=None, right=None):
self.item = data
self.left = left
self.right = right
def __str__(self):
return str(self.item)
from TreeNode import TreeNode
class BST(object):
#------------------------------------------------------------
def __init__(self):
"""create empty binary search tree
post: empty tree created"""
self.root = None
self.size = 0
def delete(self, root, item, ldepth = 0, rdepth = 0 ):
"""remove item from binary search tree
post: item is removed from the tree"""
if ldepth == 0:
ldepth == max(self.height(root.left))
if rdepth == 0:
rdepth == max(self.height(root.right))
if ldepth > rdepth:
depth = ldepth
print(depth)
elif ldepth < rdepth:
depth = rdepth
print(depth)
else:
depth = ldepth
print(depth)
self.root = self._subtreeDelete(root, item, depth)
#------------------------------------------------------------
def _subtreeDelete(self, root, item, depth):
if root is None: # Empty tree, nothing to do
return None
if item < root.item: # modify left
root.left = self._subtreeDelete(root.left, item)
elif item > root.item: # modify right
root.right = self._subtreeDelete(root.right, item)
else: # delete root
if root.left is None: # promote right subtree
root = root.right
elif root.right is None: # promote left subtree
root = root.left
else:
# root node can't be deleted, overwrite it with max of
# left subtree and delete max node from the subtree
root.item, root.left = self._subtreeDelMax(root.left)
return root
#------------------------------------------------------------
def _subtreeDelMax(self, root):
if root.right is None: # root is the max
return root.item, root.left # return max and promote left subtree
else:
# max is in right subtree, recursively find and delete it
maxVal, root.right = self._subtreeDelMax(root.right)
return maxVal, root
def height(self, root):
if root is None:
return 0
else:
return max(self.height(root.left), self.height(root.right)) + 1
from BinarySearchTree import BST
from TreeNode import TreeNode
tree = TreeNode(4, TreeNode(2, TreeNode(1), TreeNode(3)), TreeNode (7, TreeNode(6),TreeNode(9)))
a = BST()
a._subtreeInsert(tree, 10)
a._subtreeInsert(tree, 5)
a.delete(tree, 9)
print("PRE-ORDER TRANSVERSE:")
print(a.preOrder(tree))
print("IN-ORDER TRANSVERSE:")
print(a.inOrder(tree))
print("POST-ORDER TRANSVERSE:")
print(a.postOrder(tree))
print("The max depth of the tree is,", a.height(tree),"nodes deep.")
print("There are,", a.treeSize(tree),"nodes in this tree.")
Could anyone tell me whats wrong? I need this to work in order to make my delete function work properly,
The max() function in python takes an iterable object, like a list, in which it can iterates over to find the max value.
self.height(root.left)
is a single int, essentially a single value which is not iteratable, which is throwing your error.
Related
I'm unable to identify where I'm going wrong with my AVL implementation for balancing an existing binary search tree. I'm not getting any errors but my binary search tree does not come out to be properly balanced. After insertion, my binary search tree looks like (it would be prudent here to mention that my display_keys method gives us a visualization that is rotated by 90 degrees):
∅
The-Dreamers
∅
Saint-Laurent
∅
Pierrot-le-Fou
∅
Contempt
Cold-War
Before-Sunrise
∅
Basic-Instinct
∅
This is correct as it seems be to be following the rules for a BST.
But after calling the BalanceTree() method on my binary search tree, I seem to get:
∅
The-Dreamers
Saint-Laurent
Pierrot-le-Fou
Contempt
Cold-War
Before-Sunrise
Basic-Instinct
∅
which as you can see, is not Balanced. But wait, and here's the catch, if I call BalanceTree() again, the tree comes out to be perfectly balanced and isBSTBalanced returns True also. After the second call to BalanceTree(), our tree looks like:
∅
The-Dreamers
Saint-Laurent
Pierrot-le-Fou
Contempt
Cold-War
Before-Sunrise
Basic-Instinct
∅
I am adding the complete source code for my BST class for clarity and if somebody wants to execute the code, but I have added a comment (#Addition of new methods for AVL starts here) in the BST class to indicate where the methods for AVL start. You need only concern yourself with them. I would like for you help me pinpoint what exactly is going wrong in my code.
class BST:
class TreeNode:
def __init__(self, key, value, left=None, right=None, parent=None):
self.key = key
self.value = value
self.left = left
self.right = right
self.parent = parent
self.height = 1
def __init__(self):
self.root = None
self.size = 0
def __len__(self):
return self.size
def insert(self, key, value):
if self.root == None:
self.root = self.TreeNode(key, value)
else:
self._insert(key, value, self.root)
self.size += 1
def _insert(self, key, value, curr_node):
if key < curr_node.key:
if curr_node.left is not None:
self._insert(key, value, curr_node.left)
else:
curr_node.left = self.TreeNode(key, value, parent=curr_node)
elif key > curr_node.key:
if curr_node.right is not None:
self._insert(key, value, curr_node.right)
else:
curr_node.right = self.TreeNode(key, value, parent=curr_node)
def search(self, key):
if self.root:
found = self._search(key, self.root)
if found:
return found.value
else:
return None
else:
return None
def _search(self, key, curr_node):
if not curr_node:
return None
elif curr_node.key == key:
return curr_node
elif key < curr_node.key:
return self._search(key, curr_node.left)
else:
return self._search(key, curr_node.right)
def find_min(self):
curr = self.root
while curr.left is not None:
curr = curr.left
return curr
def find(self, node):
curr = node
while curr.left is not None:
curr = curr.left
return curr
def delete(self, key):
node_to_remove = self._search(key, self.root)
if node_to_remove.left is None and node_to_remove.right is None:
#Then we identify this as a leaf node
if node_to_remove is node_to_remove.parent.left:
#Setting the parent's reference to this to None
node_to_remove.parent.left = None
elif node_to_remove is node_to_remove.parent.right:
node_to_remove.parent.right = None
#2nd Case --> Two child
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
self.delete(minimum.key) #We will still have a ref to this node afterwards
node_to_remove.key, node_to_remove.value = minimum.key, minimum.value
#3rd Case -> One child
else:
if node_to_remove.left:
node_to_remove.left.parent = node_to_remove.parent
node_to_remove.parent.left = node_to_remove.left
elif node_to_remove.right:
node_to_remove.right.parent = node_to_remove.parent
node_to_remove.parent.right = node_to_remove.right
def traversal(self, root):
res = []
if root:
res = self.traversal(root.left)
res.append(root)
res = res + self.traversal(root.right)
return res
def inorder_traversal(self, root):
if root:
self.inorder_traversal(root.left)
print(root.key)
self.inorder_traversal(root.right)
#Addition of new methods for AVL starts here
def display_keys(self, node, space='\t', level=0):
"""
Allows us to visualize the tree (albiet rotated by 90 degrees)
"""
# print(node.key if node else None, level)
# If the node is empty
if node is None:
print(space*level + '∅')
return
# If the node is a leaf
if node.left is None and node.right is None:
print(space*level + str(node.key))
return
# If the node has children
self.display_keys(node.right, space, level+1)
print(space*level + str(node.key))
self.display_keys(node.left,space, level+1)
def height(self):
return self._height(self.root)
def _height(self, curr_node):
if curr_node is None:
return -1 #since we are counting number of edges, we will return -1
else:
return 1 + max(self._height(curr_node.left), self._height(curr_node.right))
def isBSTBalanced(self):
return self._isBSTBalanced(self.root)
def _isBSTBalanced(self, curr_node):
if curr_node is None:
return True
hleft_subtree = self._height(curr_node.left)
hright_subtree = self._height(curr_node.right)
if hleft_subtree - hright_subtree in [-1,0,1]:
return self._isBSTBalanced(curr_node.left) and self._isBSTBalanced(curr_node.right)
else:
return False
def balance_factor(self):
if self.root is not None:
return self._balance_factor(self.root)
else:
return 0
def _balance_factor(self, curr_node):
if curr_node is None:
return
hleft_subtree = self._height(curr_node.left)
hright_subtree = self._height(curr_node.right)
b_factor = hleft_subtree - hright_subtree
return b_factor
def BalanceTree(self):
if self.isBSTBalanced() == False:
return self._rebalance(self.root)
def _rebalance(self, curr_node):
if curr_node is None:
return None
curr_node.left = self._rebalance(curr_node.left)
curr_node.right = self._rebalance(curr_node.right)
curr_node.height = 1 + max(self._height(curr_node.left), self._height(curr_node.right))
#print(curr_node.height)
if self._balance_factor(curr_node) > 1 and self._balance_factor(curr_node.left) >= 0:
#left heavy subtree
return self._rotate_right(curr_node)
if self._balance_factor(curr_node) < -1 and self._balance_factor(curr_node.right) <= 0:
#right heavy subtree
return self._rotate_left(curr_node)
if self._balance_factor(curr_node) < 0 and self._balance_factor(curr_node.right) > 0:
self._rotate_right(curr_node.right)
return self._rotate_left(curr_node)
if self._balance_factor(curr_node) > 0 and self._balance_factor(curr_node.left) < 0:
self._rotate_left(curr_node.left)
return self._rotate_right(curr_node)
return curr_node
def _rotate_left(self, oldRoot):
newRoot = oldRoot.right #the newRoot is the right child of the previous root
oldRoot.right = newRoot.left #replacing right child of the old root with the left child of the new
if newRoot.left is not None:
newRoot.left.parent = oldRoot
newRoot.parent = oldRoot.parent
if oldRoot == self.root:
self.root = newRoot
else:
if oldRoot.parent.left is oldRoot: #Checking isLeftChild
oldRoot.parent.left = newRoot
else:
oldRoot.parent.right = newRoot
newRoot.left = oldRoot
oldRoot.parent = newRoot
oldRoot.height = 1 + max(self._height(oldRoot.left), self._height(oldRoot.right))
newRoot.height = 1 + max(self._height(newRoot.left), self._height(newRoot.right))
return newRoot
def _rotate_right(self, oldRoot):
newRoot = oldRoot.left #the newRoot is the left child of the previous root
oldRoot.left = newRoot.right #replacing left child of the old root with the right child of the new
if newRoot.right is not None:
newRoot.right.parent = oldRoot
newRoot.parent = oldRoot.parent
if oldRoot == self.root:
self.root = newRoot
else:
if oldRoot.parent.right is oldRoot: #Checking isRightChild
oldRoot.parent.right = newRoot
else:
oldRoot.parent.left = newRoot
newRoot.right = oldRoot
oldRoot.parent = newRoot
oldRoot.height = 1 + max(self._height(oldRoot.left), self._height(oldRoot.right))
newRoot.height = 1 + max(self._height(newRoot.left), self._height(newRoot.right))
return newRoot
if __name__ == '__main__':
obj = BST()
obj.insert('Basic-Instinct', 0)
obj.insert('The-Dreamers', 1)
obj.insert('Saint-Laurent', 2)
obj.insert('Pierrot-le-Fou', 3)
obj.insert('Contempt', 4)
obj.insert('Before-Sunrise', 5)
obj.insert('Cold-War', 8)
obj.display_keys(obj.root) #displays a visual representation of our tree, albeit rotated by 90 degrees
print()
print("isBSTBalanced:", obj.isBSTBalanced())
obj.BalanceTree()
print("isBSTBalanced:", obj.isBSTBalanced()) #After executing BalanceTree(), isBSTBalanced still returns False
print()
obj.display_keys(obj.root)
Progress: Revamped _isBSTBalanced method so that it visits every node recursively and not just the root node. The final outcome, however, remains the same.
Progress: I was able to identify one of the major issues being that while I was calling _rotate_left and _rotate_right methods in the _rebalance method, I was not returning them. In addition to this, I was not recursively visiting the left and right subtrees of curr_node, which was initially set to the root of the tree, to be able to traverse the tree in a bottom up manner. I have resolved this too. I have added a display_keys method which allows us to visualize the tree, albeit rotated by 90 degrees. I'm updating the code and prompt in this post accordingly. The problem that still remains is that I have to call the BalanceTree() method more than once in some cases for isBSTBalanced to return True.
I am trying to implement Binary Tree, I think the tree implementation is working fine as I am able to find my elements using if 8 in tree. But I when I am trying to perform inOrder Traversal I am running into Recursion Error.
class BinaryNode:
def init(self,value):
self.value = value
self.left = None
self.right = None
class BinaryTree:
def __init__(self):
self.root = None
def add(self, value):
if self.root == None:
self.root = BinaryNode(value)
else:
current = self.root
while 1:
if value <= current.value:
if current.left:
current = current.left
else:
current.left = BinaryNode(value)
break
elif value > current.value:
if current.right:
current = current.right
else:
current.right = BinaryNode(value)
break
else:
break
def __contains__(self, target):
node = self.root
while node is not None:
if node is not None:
if target < node.value:
node = node.left
elif target > node.value:
node = node.right
else:
return True
return False
def inorder(self,node):
node = self.root
if node is not None:
self.inorder(node.left)
print (node.value)
self.inorder(node.right)
</code>
tree = BinaryTree()
arr = [8,3,1,6]
for i in arr:
tree.add(i)
print (tree.root.value)
print ('Inorder Traversal')
tree.inorder(tree.root)
Error I am getting is "RecursionError: maximum recursion depth exceeded" :( I am trying to check that node is not none before the call, not sure where I am going wrong
I'm trying to implement a serializing/deserializing algorithm in python for binary trees.
Here's my code:
class Node:
count = 1
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def insert(self, value):
if self.value > value:
if self.left is None:
self.left = Node(value)
Node.count += 1
else:
self.left.insert(value)
else:
if self.right is None:
self.right = Node(value)
Node.count += 1
else:
self.right.insert(value)
# Using preorder
def serialize(root, serial):
if root != None:
serial.append(root.value)
serialize(root.left, serial)
serialize(root.right, serial)
else:
serial.append('x')
def deserialize(newRoot, serial):
if serial[0] == 'x':
serial.pop(0)
else:
if len(serial) > 0:
newRoot = Node(serial.pop(0))
print(newRoot.value)
deserialize(newRoot.left, serial)
deserialize(newRoot.right, serial)
print("This program serializes a tree\n")
root = Node(3)
root.insert(1)
root.insert(2)
root.insert(4)
root.insert(5)
root.insert(0)
# Serialize
serial = []
serialize(root, serial)
print(serial)
# Deserialize
newRoot = Node(None)
deserialize(newRoot, serial)
print(newRoot.value)
The problem is, newRoot doesn't get updated by deserialize because python passes it by value. How do I get around this, preferably in the most elegant way? In C/C++, I would just pass a pointer to newRoot and it should get updated accordingly. Thanks!
You can return the newly created nodes and assign them as left and right nodes. Also poping the first element of a list is more costly than poping the last element, so reverseing the list at the beginning and then using it in the recursion will be more performant in your case. So the code will become something like:
def deserialize(serial):
serial.reverse()
return _deserialize(serial)
def _deserialize(serial):
if not serial:
return None
node = None
value = serial.pop()
if value != 'x':
node = Node(value)
node.left = _deserialize(serial)
node.right = _deserialize(serial)
return node
root = deserialize(serial)
print(root.value)
You can create left and right subtree within deserialize function and return the root.
Here is my code:
node_list = []
MARKER = -1
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def serialize(root):
if root is None:
node_list.append(MARKER)
return
node_list.append(root.val)
serialize(root.left)
serialize(root.right)
def deserialize(root, node_list):
if node_list:
val = node_list.pop(0)
else:
return
if val == MARKER:
return
# Create root, left and right recursively
root = Node(val)
root.left = deserialize(root.left, node_list)
root.right = deserialize(root.right, node_list)
return root
def inorder_traversal(root):
if root:
inorder_traversal(root.left)
print(root.val, end=' ')
inorder_traversal(root.right)
if __name__=="__main__":
# Create tree
root = Node(20)
root.left = Node(8)
root.right = Node(22)
root.left.left = Node(4)
root.left.right = Node(12)
root.left.right.left = Node(10)
root.left.right.right = Node(14)
print("Inorder traversal before serialization..")
inorder_traversal(root)
print('')
# serialize the tree and insert elements into a list
serialize(root)
print(node_list)
root1 = None
root1 = deserialize(root1, node_list)
print("Inorder traversal after deserialization..")
inorder_traversal(root1)
print('')
I have the task to perform some basic operations on Binary Search Trees and I'm not sure what is the clever way to do it.
I know that the usual way would be to write a class for the nodes and one for the tree so that I can build up my tree from given values and perform certain tasks on it. The thing is, I'm already getting the tree as a list and since BSTs are not unique, there won't come any good from it if I take each value and build the tree myself.
So... I'm getting a list like this:
11 9 2 13 _, 4 18 2 14 _, 2 10 _ 11 4, 14 16 4 _ _, 13 0 11 _ _ | 10 | 7
which means:
key value parent left right, ... | value1 | value2
So as you see the BST is given explicitly. My tasks are to do a level-print of the tree, return the path from root to value1, do a rotate-right operation on the subtree that has value1, then delete value1 and then insert value2.
What would be an efficient way to tackle this problem?
Here is one possible way of implementing the tree. Hope it helps. Though this contains insertions and popular traversals, not rotations or deletions.
Reference: http://www.thelearningpoint.net/computer-science/learning-python-programming-and-data-structures/learning-python-programming-and-data-structures--tutorial-20--graphs-breadth-and-depth-first-search-bfsdfs-dijkstra-algorithm-topological-search
'''
Binary Search Tree is a binary tree(that is every node has two branches),
in which the values contained in the left subtree is always less than the
root of that subtree, and the values contained in the right subtree is
always greater than the value of the root of the right subtree.
For more information about binary search trees, refer to :
http://en.wikipedia.org/wiki/Binary_search_tree
'''
#Only for use in Python 2.6.0a2 and later
from __future__ import print_function
class Node:
# Constructor to initialize data
# If data is not given by user,its taken as None
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
# __str__ returns string equivalent of Object
def __str__(self):
return "Node[Data = %s]" % (self.data,)
class BinarySearchTree:
def __init__(self):
self.root = None
'''
While inserting values in a binary search tree, we first check
whether the value is greater than, lesser than or equal to the
root of the tree.
We initialize current node as the root.
If the value is greater than the current node value, then we know that
its right location will be in the right subtree. So we make the current
element as the right node.
If the value is lesser than the current node value, then we know that
its right location will be in the left subtree. So we make the current
element as the left node.
If the value is equal to the current node value, then we know that the
value is already contained in the tree and doesn't need to be reinserted.
So we break from the loop.
'''
def insert(self, val):
if (self.root == None):
self.root = Node(val)
else:
current = self.root
while 1:
if (current.data > val):
if (current.left == None):
current.left = Node(val)
break
else:
current = current.left
elif (current.data < val):
if (current.right == None):
current.right = Node(val)
break
else:
current = current.right
else:
break
'''
In preorder traversal, we first print the current element, then
move on to the left subtree and finally to the right subree.
'''
def preorder(self, node):
if (node == None):
return
else:
print(node.data, end=" ")
self.preorder(node.left)
self.preorder(node.right)
'''
In inorder traversal, we first move to the left subtree, then print
the current element and finally move to the right subtree.
'''
#Important : Inorder traversal returns the elements in sorted form.
def inorder(self, node):
if (node == None):
return
else:
self.inorder(node.left)
print(node.data, end=" ")
self.inorder(node.right)
'''
In postorder traversal, we first move to the left subtree, then to the
right subtree and finally print the current element.
'''
def postorder(self, node):
if (node == None):
return
else:
self.postorder(node.left)
self.postorder(node.right)
print(node.data, end=" ")
tree = BinarySearchTree()
tree.insert(1)
tree.insert(9)
tree.insert(4)
tree.insert(3)
tree.insert(5)
tree.insert(7)
tree.insert(10)
tree.insert(0)
print ("Preorder Printing")
tree.preorder(tree.root)
print("\n\nInorder Printing")
tree.inorder(tree.root)
print("\n\nPostOrder Printing")
tree.postorder(tree.root)
Here is the implementation of Binary Search Tree with it's basic operations like insert node, find node
class Node:
def __init__(self,data):
self.left = None
self.right = None
self.data = data
class BST:
def __init__(self):
self.root = None
def set_root(self,data):
self.root = Node(data)
def insert_node(self,data):
if self.root is None:
self.set_root(data)
else:
n = Node(data)
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
else:
troot.left = n
break
else:
if troot.right:
troot = troot.right
else:
troot.right = n
break
def search_node(self,data):
if self.root is None:
return "Not found"
else:
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
if troot.data == data:
return "Found"
else:
return "Not found"
elif data > troot.data:
if troot.right:
troot = troot.right
if troot.data == data:
return "Found"
else:
return "Not found"
else:
return "Found"
tree = BST()
tree.insert_node(10)
tree.insert_node(5)
tree.insert_node(20)
tree.insert_node(7)
print(tree.root.data)
print(tree.root.left.data)
print(tree.root.right.data)
print(tree.root.left.right.data)
print(tree.search_node(10))
print(tree.search_node(5))
print(tree.search_node(20))
print(tree.search_node(7))
print(tree.search_node(12))
print(tree.search_node(15))
Output:
10
5
20
7
Found
Found
Found
Found
Not found
Not found
In this specific case I had success using a dictionary as a datatype to store the graph. The key is the node_key and the value is a list with the attributes of the node. In this way it is rather fast to find the needed nodes and all its attributes.
I'm just not sure if there is a way to make it reasonably faster.
In my binary search tree I am making a depth function which will tell the user what is the depth of the tree they have insert. This function will be crucial for my unique delete function that deletes a node from the largest depth-sided node. I think I know where the problem is exactly but I'm not sure.
This is my error I keep receiving.
C:\Python33\python.exe "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter7/Test.py"
Traceback (most recent call last):
PRE-ORDER TRANSVERSE:
File "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter7/Test.py", line 19, in <module>
4
print("The max depth of the tree is,", a.height(tree),"nodes deep.")
2
File "C:\Users\koopt_000\Desktop\College\Sophomore Semester 2\Computer Science 231\Chapter7\BinarySearchTree.py", line 245, in height
1
3
7
6
5
10
None
IN-ORDER TRANSVERSE:
1
2
3
4
5
6
7
10
None
POST-ORDER TRANSVERSE:
1
return max(BST.height(root.left), BST.height(root.right)) + 1
3
TypeError: height() missing 1 required positional argument: 'root'
2
5
6
10
7
4
None
Process finished with exit code 1
Now I Think my problem arises in this section of code:
return max(BST.height(root.left), BST.height(root.right)) + 1
I believe this statement is what is causing it due to the fact that it is making me call the BST function which the height function is already in for it to 'work'. I simply tried "height.(root.left)", which did not work because it said there is no global variable height. Which isn't the case I don't believe.
Here is my full list of code for my function, starting with my tree node, then my BST file (main), and then my test code.
class TreeNode(object):
def __init__(self, data = None, left=None, right=None):
self.item = data
self.left = left
self.right = right
def __str__(self):
return str(self.item)
from TreeNode import TreeNode
class BST(object):
#------------------------------------------------------------
def __init__(self):
"""create empty binary search tree
post: empty tree created"""
self.root = None
self.size = 0
def delete(self, item):
"""remove item from binary search tree
post: item is removed from the tree"""
self.root = self._subtreeDelete(self.root, item)
#------------------------------------------------------------
def _subtreeDelete(self, root, item):
if root is None: # Empty tree, nothing to do
return None
if item < root.item: # modify left
root.left = self._subtreeDelete(root.left, item)
elif item > root.item: # modify right
root.right = self._subtreeDelete(root.right, item)
else: # delete root
if root.left is None: # promote right subtree
root = root.right
elif root.right is None: # promote left subtree
root = root.left
else:
# root node can't be deleted, overwrite it with max of
# left subtree and delete max node from the subtree
root.item, root.left = self._subtreeDelMax(root.left)
return root
def _subtreeDelMax(self, root):
if root.right is None: # root is the max
return root.item, root.left # return max and promote left subtree
else:
# max is in right subtree, recursively find and delete it
maxVal, root.right = self._subtreeDelMax(root.right)
return maxVal, root
def height(self, root):
if root is None:
return 0
else:
return max(BST.height(root.left), BST.height(root.right)) + 1
from BinarySearchTree import BST
from TreeNode import TreeNode
tree = TreeNode(4, TreeNode(2, TreeNode(1), TreeNode(3)), TreeNode (7, TreeNode(6),TreeNode(9)))
a = BST()
a._subtreeInsert(tree, 10)
a._subtreeInsert(tree, 5)
a._subtreeDelete(tree, 9)
print("PRE-ORDER TRANSVERSE:")
print(a.preOrder(tree))
print("IN-ORDER TRANSVERSE:")
print(a.inOrder(tree))
print("POST-ORDER TRANSVERSE:")
print(a.postOrder(tree))
print("The max depth of the tree is,", a.height(tree),"nodes deep.")
print("There are,", a.treeSize(tree),"nodes in this tree.")
Does anyone see the reason why my height function isn't working properly? Thanks!
Your function height is an instance method of the class BST, you need to call it via self and not with the class BST.
So in your particular case this is:
def height(self, root):
if root is None:
return 0
else:
return max(self.height(root.left), self.height(root.right)) + 1
However, your function height actually does not rely on any data associated directly with the search tree. self is only needed to continue the recursion. Thus, you could also turn it into static method via the staticmethod decorator:
#staticmethod
def height(root):
if root is None:
return 0
else:
return max(BST.height(root.left), BST.height(root.right)) + 1
Alternatively, you could also move the function out of the BST class entirely and get rid off BST.height and just call it via height.
From the code you posted, this holds for basically all functions of the BST class. I don't really see a need for it. You may only use the TreeNode and some top-level functions (without the BST class) in your python module to modify and interact with your tree.