I have defined the BinarySearchTree class below:
class BinarySearchTree:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def insert(self, new_data):
if new_data == self.data:
return
elif new_data < self.data:
if self.left == None:
self.left = BinarySearchTree(new_data)
else:
self.left.insert(new_data)
else:
if self.right == None:
self.right = BinarySearchTree(new_data)
else:
self.right.insert(new_data)
def search(self, find_data):
if self.data == find_data:
return True
elif find_data < self.data and self.left != None:
return self.left.search(find_data)
elif find_data > self.data and self.right != None:
return self.right.search(find_data)
else:
return False
def get_data(self):
return self.data
def set_data(self, new_data):
self.data = new_data
def get_left(self):
return self.left
def get_right(self):
return self.right
Using this class implementation now I need to create a binary tree as shown in the vertical representation:
>>> bst = create_bst()
print_tree(bst, 0)
27
(L) 14
(L) 10
(R) 19
(R) 35
(L) 31
(R) 42
With my code here:
def create_bst():
root = BinarySearchTree(27)
root.insert(14)
root.insert(10)
root.get_left().insert(19)
root.get_left().insert(35)
root.get_left().get_left().insert(31)
root.get_left().get_right().insert(42)
return root
This is the representation I'm getting:
27
(L) 14
(L) 10
(R) 31
(R) 19
(R) 35
(R) 42
It seems to be working fine so far. Just put all the elements directly into root without using get_left, get_right (since you are inserting them into the wrong node).
def create_bst():
root = BinarySearchTree(27)
root.insert(14)
root.insert(10)
root.insert(19)
root.insert(35)
root.insert(31)
root.insert(42)
return root
Related
I have coded an AVL Tree and my logic for the rotations is correct but I am still not able to get it working properly. For rotations on the root node my rotations work properly but if the rotation is further down the tree, the parent node does not point to the new node that has been rotated into place and continues to point to the node that was in place before the rotation. I am pretty sure the issues lies with my insert method but I am not sure how to get the parent node to point to the new node when a rotation occurs. I know you can add a parent variable to fix this but I am wondering if there is a way to do it without that.
For example
10 10 10
/ \ / \ instead of / \
8 12 Rotates to -> 8 12 6 12
/ \ \ / \ \
6 14 14 4 8 14
/ 4 and 6 are lost
4
class AVL():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.height = 0
self.balf = 0
def getData(self):
return self.data
def getHeight(self):
return self.height
def heightCalc(self,node):
if node is None:
return -1
else:
return max(self.heightCalc(node.left), self.heightCalc(node.right)) + 1
def getBalanceFactor(self):
return self.balf
def balCheck(self, node):
if node is None:
return -1
else:
return self.heightCalc(node.left) - self.heightCalc(node.right)
def insert(self, data):
if data is not None:
if self.data is None:
self.data = data
else:
if data < self.data:
if self.left is None:
self.left = AVL(data)
else:
self.left.insert(data)
elif data >= self.data:
if self.right is None:
self.right = AVL(data)
else:
self.right.insert(data)
self.height=self.heightCalc(self)
self.balf = self.balCheck(self)
if self.balf > 1:
if self.left.getBalanceFactor() < 0:
self.left = self.left.leftRotate()
return self.rightRotate()
else:
return self.rightRotate()
elif self.balf < -1:
if self.right.getBalanceFactor() > 0:
self.right = self.right.rightRotate()
return self.leftRotate()
else:
return self.leftRotate()
return self
def leftRotate(self):
temp = self.right
temp2 = self.right.left
self.right.left = self
self.right = temp2
self.height = self.heightCalc(self)
temp.height = self.heightCalc(temp)
self.balf = self.balCheck(self)
temp.balf = self.balCheck(temp)
return temp
def rightRotate(self):
tmp = self.left
tmp1 = self.left.right
self.left.right = self
self.left = tmp1
self.height = self.heightCalc(self)
tmp.height = self.heightCalc(tmp)
self.balf = self.balCheck(self)
tmp.balf = self.balCheck(tmp)
return tmp
#This example works properly
test = AVL(10)
test= test.insert(12)
test = test.insert(8)
print(test.data) #outputs 8
print(test.left.data) #outputs 7
print(test.right.data) #outputs 10
#In this case the rotation occurs but the parent node does not update its left child to the new node and still points to 8
test2 = AVL(10)
test2 = test2.insert(12)
test2 = test2.insert(8)
test2 = test2.insert(14)
test2 = test2.insert(6)
test2 = test2.insert(4)
print(test2.data)#outputs 10
print(test2.left.data)#outputs 8 but should be 6
#4 and 6 can no longer be accessed because they are lost
In your code, the insert method returns the new root of the subtree, after the insertion has been done and any needed rotations have happened. Your issue is that you're not using that return value when you recursively call insert on one of your child nodes.
if data < self.data:
if self.left is None:
self.left = MyAVL(data)
else:
self.left = self.left.insert(data) # update self.left here
elif data >= self.data:
if self.right is None:
self.right = MyAVL(data)
else:
self.right = self.right.insert(data) # and self.right here
I am on the way of learning data structures and facing a problem which is related with python and recursion.
I have a function (below - called update_BST) and in one version of the code doesn't keep the correct value from recursion.
I provide the two version of the code snippet.
Thanks
"""
Given a Binary Search Tree (BST),
modify it so that all greater values in
the given BST are added to every node.
For example, consider the following BST.
50
/ \\
30 70
/ \ / \\
20 40 60 80
The above tree should be modified to following
260
/ \\
330 150
/ \ / \\
350 300 210 80
"""
class Node:
def __init__(self, data):
self.data = data
self.right = None
self.left = None
def insert(self, data):
if self.data == data:
return False
elif self.data > data:
if self.left:
self.left.insert(data)
else:
self.left = Node(data)
else:
if self.right:
self.right.insert(data)
else:
self.right = Node(data)
def in_order(self):
if self:
if self.left:
self.left.in_order()
print(self.data)
if self.right:
self.right.in_order()
class BST:
def __init__(self):
self.root = None
def insert(self, data):
if self.root:
self.root.insert(data)
else:
self.root = Node(data)
return True
def in_order(self):
if self.root is not None:
self.root.in_order()
bst = BST()
arr = [50, 30, 20, 40, 70, 60, 80]
for i in arr:
bst.insert(i)
def update_BST(node, temp):
if node == None:
return
update_BST(node.right, temp)
temp[0] = temp[0] + node.data
node.data = temp[0]
update_BST(node.left, temp)
update_BST(bst.root, [0])
bst.in_order()
This codes works as it suppose to work. It gives back the right values.
BUT, I don't understand why it is not working if I use -- 0 -- instead of the -- [0] -- and of course modifying the reamining code like:
def update_BST(node, temp):
if node == None:
return
update_BST(node.right, temp)
temp = temp + node.data
node.data = temp
update_BST(node.left, temp)
update_BST(bst.root, 0)
So the question is why I need to use the [0] - why the simple integer 0 is not working?
I'm implementing a (recursive) binary search tree and I can't get the size function working. This is my code so far:
class BinarySearchTreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def __str__(self):
return str(self.data)
def add(self, data):
if self.data == data:
return False
elif data < self.data:
if self.left:
return self.left.add(data)
else:
self.left = BinarySearchTreeNode(data)
return True
else:
if self.right:
return self.right.add(data)
else:
self.right = BinarySearchTreeNode(data)
return True
def contains(self, data):
if self.data == data:
return True
elif self.data > data:
if self.left:
return self.left.contains(data)
else:
return False
else:
if self.right:
return self.right.contains(data)
else:
return False
def size(self):
if self.left and self.right:
return 1 + self.left.size() + self.right.size()
elif self.left:
return 1 + self.left.size()
elif self.right:
return 1 + self.right.size()
else:
return 1
class BinarySearchTree:
def __init__(self):
self.root = None
def add(self, data):
if not self.root:
self.root = BinarySearchTreeNode(data)
return True
else:
return self.root.add(data)
def contains(self, data):
if self.root:
return self.root.contains(data)
else:
return False
def clear(self):
self.root = None
def size(self):
if self.root is None:
return 0
else:
return self.root.size()
bst = BinarySearchTree()
bst.add(3)
bst.add(24)
bst.add(7)
bst.add(15)
bst.add(2)
bst.add(19)
bst.size()
I want the size function to be called from the BinarySearchTree class but executed via the BinarySearchTreeNode class. I have tried everything I can think of, but nothing works. What am I doing wrong?
What is this?
class BinarySearchTreeNode:
self.data = data
self.left = None
self.right = None
This is not an initializing process you're doing there mate. Try the following:
class BinarySearchTreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
Even checked it for you:
In[1]:
bst = BinarySearchTree()
bst.add(3)
bst.add(24)
bst.add(7)
bst.add(15)
bst.add(2)
bst.add(19)
bst.size()
Out[2]: 6
I am trying to implement binary search tree in pythonand trying to print the nodes of a tree in inorder, preorder and postorder but unfortunately my results are not correct.
Here is my code:
class Node:
def __init__(self, val):
self.v = val
self.l = None
self.r = None
class BinarySearchTree:
def __init__(self):
self.root = None
def get_root(self):
return self.root
def insert(self, val):
if self.root is None:
self.root = Node(val)
else:
self._add(val, self.root)
def _add(self, val, node):
if val < node.l:
if node.l is None:
node.l = Node(val)
else:
self._add(val, node.l)
else:
if node.r is None:
node.r = Node(val)
else:
self._add(val, node.r)
def find(self, val):
if self.root is None:
return None
else:
self._find(val, self.root)
def _find(self, val, node):
if val == node.v:
return Node
else:
if val < node.v and node is not None:
self._find(val, node.l)
if val > node.v and node is not None:
self._find(val, node.r)
def delete_tree(self):
self.root = None
def print_in_order(self): # Left, Node, Right
if self.root is None:
return None
else:
self._in_order(self.root)
def _in_order(self, node):
if node is not None:
self._in_order(node.l)
print str(node.v) + ' '
self._in_order(node.r)
def print_pre_order(self): # Node, Left, Right
if self.root is None:
return None
else:
self._pre_order(self.root)
def _pre_order(self, node):
if node is not None:
print str(node.v) + ' '
self._pre_order(node.l)
self._pre_order(node.r)
def print_post_order(self): # Left, Right, Node
if self.root is None:
return None
else:
self._post_order(self.root)
def _post_order(self, node):
if node is not None:
self._post_order(node.l)
self._post_order(node.r)
print str(node.v) + ' '
if __name__ == '__main__':
t = BinarySearchTree()
t.insert(20)
t.insert(10)
t.insert(30)
t.insert(5)
t.insert(15)
t.insert(25)
t.insert(35)
print 'In Order Traversal: \n', t.print_in_order()
print '\nPre Order Traversal: \n', t.print_pre_order()
print '\nPost Order Traversal:\n', t.print_post_order()
Can someone please tell me what am I doing wrong?
My output is in the following: Inorder and Preorder is returning the same output.
In Order Traversal:
20
10
30
5
15
25
35
None
Pre Order Traversal:
20
10
30
5
15
25
35
None
Post Order Traversal:
35
25
15
5
30
10
20
None
Traversal functions are okay. But in _add, the following comparison:
if val < node.l:
...
should be replaced with:
if val < node.v:
...
to compare new value with current node value, instead of the left node which cause wrong comparison result; results in wrong tree structure.
When I try to append the values to the global list it shows an error。
list1 = []
class Node:
def __init__(self,data):
self.data = data
self.left = None
self.right = None
self.root = None
def getData(self):
return self.data
def setData(self,data):
self.data = data
def insertleft(self,data):
if self.left == None:
self.left = Node(data)
return
else:
self.left.setData(data)
return
def insertright(self,data):
if self.right == None:
self.right = Node(data)
return
else:
self.right.setData(data)
return
def insert(self,data):
if self.data == data:
return -1
elif self.data > data:
self.insertleft(data)
else:
self.insertright(data)
def preorder(self,list1):
if self.root:
global list1.append(self.root)
preorder(self.left,global list1)
preorder(self.right,global list1)
return list1
a = Node(99)
a.insert(10)
a.insert(101)
a.insert(108)
a.insert(9)
print a.preorder(global list1)