I'm trying to implement Binary Tree insert method with recursive calls. When i run insert function it gives me an AtributeError : BinTree instance has no atribute 'root. Can you tell me pls how I can fix it??
from random import randint
class Node:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
class BinTree:
def __init___(self):
self.root = None
def insert(self, value):
if self.root == None:
self.root = Node(value)
else:
self._insert(value, self.root)
def _insert(self, value, curr_node):
if value < curr_node.value:
if curr_node.left == None:
curr_node.left = Node(value)
else:
self._insert(value, curr_node.left)
elif value>curr_node.value:
if curr_node.right == None:
curr_node.right = Node(value)
else:
self._insert(value, curr_node.rigth)
else:
print('Node already exist!')
def printTree(self):
if self.root != None:
self._printTree(self.root)
def _printTree(self, curr_node):
if curr_node !=None:
self._printTree(curr_node.left)
print(str(curr_node.val))
self._printTree(curr_node.right)
def fillTree(tree):
for _ in range(100):
curr_elem = randint(0,50)
tree.insert(curr_elem)
return tree
tree = BinTree()
fillTree(tree)
tree.printTree()
Your __init__ has a typo in the name. There are 3 trailing underscores. Change it to:
...
class BinTree:
def __init__(self):
self.root = None
And your code should work
Edit: found a couple of more issues. Here's the complete fixed code:
from random import randint
class Node:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
class BinTree:
def __init__(self):
self.root = None
def insert(self, value):
if self.root == None:
self.root = Node(value)
else:
self._insert(value, self.root)
def _insert(self, value, curr_node):
if value < curr_node.value:
if curr_node.left == None:
curr_node.left = Node(value)
else:
self._insert(value, curr_node.left)
elif value>curr_node.value:
if curr_node.right == None:
curr_node.right = Node(value)
else:
self._insert(value, curr_node.right)
else:
print('Node already exist!')
def printTree(self):
if self.root != None:
self._printTree(self.root)
def _printTree(self, curr_node):
if curr_node !=None:
self._printTree(curr_node.left)
print(str(curr_node.value))
self._printTree(curr_node.right)
def fillTree(tree):
for _ in range(100):
curr_elem = randint(0,50)
tree.insert(curr_elem)
return tree
tree = BinTree()
fillTree(tree)
tree.printTree()
Only BinTrees have roots; the children of a BinTree are Nodes, not BinTrees and thus don't have roots.
Related
class Node:
def __init__(self, data, parent):
self.leftChild = None
self.rightChild = None
self.parent = parent
self.data = data
class BST:
def __init__(self):
self.root = None
self.count = 0
def insert(self, data):
self.count +=1
if self.root is None:
self.root = Node(data, None)
else:
self.insertNode(data,self.root)
def insertNode(self, data, parentNode):
if data < parentNode.data:
if parentNode.leftChild is not None:
self.insertNode(data, parentNode.leftChild)
else:
parentNode.leftChild = Node(data, parentNode)
else:
if parentNode.rightChild is not None:
self.insertNode(data, parentNode.rightChild)
else:
parentNode.rightChild = Node(data, parentNode)
def get_max(self, node):
if node.rightChild:
self.get_max(node.rightChild)
else:
print(node.data)
# return node.data
# return node.data
def traverse(self):
if(self.root is not None):
self.traverse_InOrder(self.root)
def traverse_InOrder(self, node):
if node.leftChild is not None:
self.traverse_InOrder(node.leftChild)
print(node.data, end=" ")
if node.rightChild is not None:
self.traverse_InOrder(node.rightChild)
bst = BST()
bst.insert(22)
bst.insert(2)
bst.insert(21)
bst.insert(23)
bst.insert(45)
bst.insert(43)
bst.insert(20)
bst.traverse()
print()
bst.get_max(bst.root)
print(bst.get_max(bst.root))
In the get_max function when I'm printing node.data it's working fine, but as soon as I'm returning the data and trying to print it as shown in last line of code, it's returning none.
I don't understand the underlying concept behind it.
Maybe it is something that I'm doing wrong.
Please explain.
Change the get_max function so it returns the rightmost node:
def get_max(self, node):
if node.rightChild:
return self.get_max(node.rightChild)
else:
return node.data
I have a problem related to class instance value problem. This code below consists of a Binary Tree class and some search methods(Depth-First-Search) which are pre-order and in-order algorithms.
The code is 100% working the problem is when I debug the root.in_order() function print out b,a,c but expected return values are d,b,a,e,c,f.
class Node:
def __init__(self, value):
self.value = value
self.left_hand = None
self.right_hand = None
def insert_left(self,value):
if self.left_hand == None:
self.left_hand = Node(value)
else:
new_node = Node(value)
new_node.left_hand = self.left_hand
self.left_hand = new_node
def insert_right(self,value):
if self.right_hand == None:
self.right_hand = Node(value)
else:
new_node = Node(value)
will_be_loaded_right_child = self.right_hand
self.right_hand = new_node
new_node.right_hand = will_be_loaded_right_child
def pre_order(self):
print(self.value.value)
print(repr(self.value))
if self.left_hand:
self.left_hand.pre_order()
if self.right_hand:
self.right_hand.pre_order()
def in_order(self):
if self.left_hand:
self.left_hand.in_order()
print(self.value)
if self.right_hand:
self.right_hand.in_order()
def __str__(self):
return "{}".format(self.value)
def printAtt(self , arr = []):
if arr.count>1:
try:
arr = [self.value, self.left_hand.value, self.right_hand.value]
print(arr)
except AttributeError:
print("""There is nothing to show of the root |-> {} <-|
Node |-> {} <-| has not right or left handside value,
please continue to add or it
could be the last child:D""".format(self.value.value, self.value.value))
root = Node("a")
node_b = Node("b")
node_c = Node("c")
node_d = Node("d")
node_e = Node("e")
node_f = Node("f")
root.insert_left(node_b)
root.insert_right(node_c)
node_b.insert_right(node_d)
node_c.insert_left(node_e)
node_c.insert_right(node_f)
root.in_order()
Just change the last part of the script since insert_left and
insert_right expects value.
Updated Version as follows:
class Node:
def __init__(self, value):
self.value = value
self.left_hand = None
self.right_hand = None
def insert_left(self,value):
if self.left_hand == None:
self.left_hand = Node(value)
else:
new_node = Node(value)
new_node.left_hand = self.left_hand
self.left_hand = new_node
def insert_right(self,value):
if self.right_hand == None:
self.right_hand = Node(value)
else:
new_node = Node(value)
will_be_loaded_right_child = self.right_hand
self.right_hand = new_node
new_node.right_hand = will_be_loaded_right_child
def pre_order(self):
print(self.value)
if self.left_hand:
self.left_hand.pre_order()
if self.right_hand:
self.right_hand.pre_order()
def in_order(self):
if self.left_hand:
self.left_hand.in_order()
print(self.value)
if self.right_hand:
self.right_hand.in_order()
def post_order(self):
if self.left_hand:
self.left_hand.post_order()
if self.right_hand:
self.right_hand.post_order()
print(self.value)
root = Node("a")
root.insert_left("b")
root.insert_right("c")
node_b = root.left_hand
node_c = root.right_hand
node_b.insert_right("d")
node_c.insert_left("e")
node_c.insert_right("f")
root.in_order()
print("*"*30)
root.pre_order()
print("*"*30)
root.post_order()
Here's my programme of Binary Search Tree, all the functions are working in uploading system, except the last one, I somehow have to find out which of the Nodes I visited throughout calling previous functions. Any ideas?
class Node:
def __init__(self, value):
self.left = None
self.right = None
self.data = value
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self, value):
if self.root is None:
self.root = Node(value)
else:
self._insert(value, self.root)
def _insert(self, value, curNode):
if value < curNode.data:
if curNode.left is None:
curNode.left = Node(value)
else:
self._insert(value, curNode.left)
else:
if curNode.right is None:
curNode.right = Node(value)
else:
self._insert(value, curNode.right)
def fromArray(self, array):
for i in range(len(array)-1):
value = array[i]
self.insert(value)
i += 1
def search(self, value):
if self.root is not None:
return self._search(value, self.root)
else:
return False
def _search(self, value, curNode):
if value == curNode.data:
return True
elif value < curNode.data and curNode.left is not None:
self._search(value, curNode.left)
elif value > curNode.data and curNode.right is not None:
self._search(value, curNode.right)
else:
return False
def min(self):
curNode = self.root
while curNode.left is not None:
curNode = curNode.left
return curNode
def max(self):
curNode = self.root
while curNode.right is not None:
curNode = curNode.right
return curNode
def visitedNodes(self):
pass
And it has to return the values of nodes in list.
The straight forward answer would be to add a visited flag to each node, that is explicitly flipped in each of your functions when a Node is visited:
class Node:
def __init__(self, value):
self.left = None
self.right = None
self.data = value
self.visited = False
and then:
def _search(self, value, curNode):
curNode.visited = True
if value == curNode.data:
return True
# etc., unchanged
Same for min and max, and finally:
def visitedNodes(self, current=self.root, accumulator=[]):
if current == None:
return
if current == self.root:
accumulator = []
if current.visited:
accumulator.append(current)
visitedNodes(current.left)
visitedNodes(current.right)
return accumulator
This is just one implementation, there are many other ways to do this. I also assume this function, which traverses the whole tree, should not set the visited flag.
If you don't want to modify your current code, maybe this can help you:
class Node:
def __init__(self, value):
self.left = None
self.right = None
self._data = value
self.visited = False
#property
def data(self):
self.visited = True
return self._data
#data.setter
def data(self, value):
self.visited = False
self._data = value
n = Node(3)
print(n.visited)
print(n.data)
print(n.visited)
Output:
False
3
True
Then in your visitedNodes method you would have to look at the visited attribute of everynode. (Which will be slow)
Other way of doing it is adding a new set attribute to your BinarySearchTree and manually add a node each time you look at it, this will make you modify your code.
I am implementing BST in python and having some trouble on insertion function.
class Node:
def __init__(self, val):
self.data = val
self.Leftchild = self.Rightchild = None
class Tree:
def __init__(self):
self.root = None
def insert(self, val):
if self.root is None:
self.root = Node(val)
return self.root
else:
if self.root.data <= val:
self.root.Rightchild = self.insert(self.root.Rightchild, val)
else:
self.root.Leftchild = self.insert(self.root.Leftchild, val)
return self.root
if __name__ == '__main__':
tree = Tree()
for i in range(10):
tree.insert(random.randint(0,100))
I got TypeError on recursive.
TypeError: insert() takes 2 positional arguments but 3 were given
Isn't self.root.Rightchild or self.root.Leftchild considered same as self?
If my thought is wrong, how can I implement recursive insertion function in this case?
Thanks in advance!
You should have insert take another argument, root, and do your operations on that. You'll need to modify the recursive logic too. Have insert work exclusively with the Node data.
You should handle cases where an item already exists. You don't want duplicates put into the tree.
In the recursive case, you are calling insert on the wrong object.
Also, the two are not the same. self refers to the current Tree object, and self.root refers to the current Tree's Node object, and so on.
This is how you'd modify your function:
def insert(self, root, val):
if root is None:
return Node(val)
else:
if root.data <= val:
root.Rightchild = self.insert(root.Rightchild, val)
else:
root.Leftchild = self.insert(root.Leftchild, val)
return root
Try this one if you need class and its instance
import random
class Node:
def __init__(self, val):
self.data = val
self.Leftchild = self.Rightchild = None
class Tree:
def insert(self,root, val):
if root is None:
root = Node(val)
return root
else:
if root.data <= val:
root.Rightchild = self.insert(root.Rightchild, val)
else:
root.Leftchild = self.insert(root.Leftchild, val)
return root
def inorder(self, root):
if root:
self.inorder(root.Leftchild)
print root.data,
self.inorder(root.Rightchild)
if __name__ == '__main__':
tree = Tree()
root = None
for i in range(10):
root = tree.insert(root, random.randint(0,100))
tree.inorder(root)
Try this..
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def inorder(root):
if root:
inorder(root.left)
arr.append(root.data)
print root.data,
inorder(root.right)
def insert(root, data):
node = Node(data)
if root is None:
root = node
elif root.data >= data:
if root.left is None:
root.left = node
else:
insert(root.left, data)
else:
if root.right is None:
root.right = node
else:
insert(root.right, data)
if __name__ == '__main__':
root = Node(50)
insert(root, 30)
insert(root, 20)
insert(root, 40)
insert(root, 70)
insert(root, 60)
insert(root, 80)
inorder(root)
I'm trying to implement a BST, and am working on insert. I want to be able to call something simple, like tree.insert(Node(1)). But the issue is that this binaryInsert doesn't persist. What's the best way to achieve this functionality?
class Node:
def __init__(self, data):
self.value = data
self.rightChild = None
self.leftChild = None
class Tree:
def __init__(self):
self.root = None
def binaryInsert(self, root, node):
if root == None:
root = node
else:
if root.value > node.value:
if root.leftChild == None:
root.leftChild = node
else:
self.binaryInsert(root.leftChild, node)
else:
if root.rightChild == None:
root.rightChild = node
else:
self.binaryInsert(root.rightChild, node)
def insert(self, node):
self.binaryInsert(self.root, node)
consider these lines from your code:
def binaryInsert(self, root, node):
if root == None:
root = node
here you are just overriding a local root variable (scoped to the method), I've corrected your code, feel free to ask any question:
class Node:
def __init__(self, data):
self.value = data
self.rightChild = None
self.leftChild = None
class Tree:
def __init__(self):
self.root = None
def binaryInsert(self, tree, node):
if tree.root == None:
tree.root = node
else:
if tree.root.value > node.value:
if tree.root.leftChild == None:
tree.root.leftChild = node
else:
self.binaryInsert(tree.root.leftChild, node)
else:
if tree.root.rightChild == None:
tree.root.rightChild = node
else:
self.binaryInsert(tree.root.rightChild, node)
def insert(self, node):
self.binaryInsert(self, node)