Binary Search Tree inorder not working (python) - python

I've been messing around learning about objects and classes, and as I finally felt that I managed to wrap my head around how to construct a Binary Search Tree in python, I ran into an issue. Here's my code:
class node:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self):
self.root = None
def add(self,current,value):
if self.root == None:
self.root = node(value)
else:
if value < current.value:
if current.left == None:
current.left = node(value)
else:
self.add(current.left,value)
if value > current.value:
if current.right == None:
current.right = node(value)
else:
self.add(current.right,value)
def visit(self,node):
print(node.value)
def inorder(self,current):
self.inorder(current.left)
self.visit(current)
self.inorder(current.right)
Tree = BST()
root = node(2)
Tree.root = root
Tree.add(Tree.root,7)
Tree.inorder(Tree.root)
after running the code, I got an error: AttributeError: 'NoneType' object has no attribute 'left'.
The error comes out of the inorder function, as apparently the value I'm inserting into the function is an object without a type.
as you can see, the root of the tree is a node object, so it should have the attribute "left" as per coded in the class. I would really appreciate if someone could help me with what I'm getting wrong.
Thanks in advance!
EDIT: I should note that I checked whether the root is a node with the isinstance(), function, and indeed it returned True.

I think you sould check current is not None before access its left and right.
def inorder(self, current):
if current:
self.inorder(current.left)
self.visit(current)
self.inorder(current.right)

Your design has some problems. The Tree should be the only object that knows about the root. You shouldn't have to pass the root in. Notice how this is simpler to use:
class node:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self):
self.root = None
def add(self,value,current=None):
if not self.root:
self.root = node(value)
return
if not current:
current = self.root
if value < current.value:
if not current.left:
current.left = node(value)
else:
self.add(value,current.left)
else:
if not current.right:
current.right = node(value)
else:
self.add(value, current.right)
def visit(self,node):
print(node.value)
def inorder(self,current=-1):
if current == -1:
current = self.root
if not current:
return
self.inorder(current.left)
self.visit(current)
self.inorder(current.right)
Tree = BST()
Tree.add(2)
Tree.add(7)
Tree.inorder()

Related

BST (binary search tree) not working ?? what is the mistake in this code?

class node :
def __init__(self, data, left= None, right = None):
self.data = data
self.left = left
self.right = right
class bst:
def __init__(self):
self.head = None
def insertNode(self, data):
newnode = node(data)
if self.head == None:
self.head = newnode
else:
current = self.head
while current is not None:
if data > current.data:
current = current.right
else:
current = current.left
current = newnode
bst = bst()
bst.insertNode(5)
bst.insertNode(10)
bst.insertNode(2)
current = bst.head
print(current.data)
print(current.right)
I have written a code for the best where the head is always pointing to the root node and there is a while loop which is to find the path to insert the new element to the tree but it is not woking ?? why
In this situation, it may be easier to understand and complete the problem using a recursive approach. We can use recursion to explore the tree, traversing all nodes. Try something like this:
def insert(root, data):
if root is None:
return Node(data)
else:
if root.data == data:
return root
elif root.data < data:
root.right = insert(root.right, data)
else:
root.left = insert(root.left, data)
return root
In your while loop before assigning current to either the Left or Right Tree
check whether the Left or Right Child is None, then add a stop condition (break) if the child is None and you have assigned the newnode to it as in the code below
class node :
def __init__(self, data, left= None, right = None):
self.data = data
self.left = left
self.right = right
class bst:
def __init__(self):
self.head = None
def insertNode(self, data):
newnode = node(data)
if self.head == None:
self.head = newnode
else:
current = self.head
while current is not None:
if data > current.data:
if current.right!=None:
current = current.right
else:
current.right=newnode
break
else:
if current.left!=None:
current = current.left
else:
current.left=newnode
break
current = newnode
bst = bst()
bst.insertNode(5)
bst.insertNode(10)
bst.insertNode(2)
current = bst.head
print(current.data)
print(current.right)
The problem is that you are separating the tree and the search into different classes, also, you initialize left and right as None and they will never be giving a value, so your loop will always end setting current as None.
Here is an example of what you are trying to make.
class Tree(object):
def __init__(self, entry, left=None, right=None):
self.entry = entry
self.left = left
self.right = right
def insert(self, item, tree):
if (item < tree.entry):
if (tree.left != None):
self.insert(item, tree.left)
else:
tree.left = Tree(item)
else:
if (tree.right != None):
self.insert(item, tree.right)
else:
tree.right = Tree(item)
As you can see I added a check for right and left in case they are None, in which case they are given the item's value.
The problem lies in the current = newnode. You should not directly assign newnode to current, which will only rebind current to it.
def insert(self, data):
current = self.head
parent = None
while current is not None:
if data == current.data:
return
parent = current
current = current.left if data < current.data else current.right
newnode = node(data)
if parent is None:
self.head = newnode
elif data < parent.data:
parent.left = newnode
else:
parent.right = newnode
Your mistakes are similar to the following:
>>> lst = [None, None]
>>> current = lst[0]
>>> print(current)
None
>>> current = 1
>>> lst # not change
[None, None]
current simply points to the first item in the list. If you re assign value, you will only make current point to other value, which will not modify the contents of the list.

Implementation of a Binary Search Tree in Python with BST Class and Node Class

Can Anyone help me figure out What it the wrong thing I did so I get this output Error--> NameError: name 'root' is undefined.
When I test the program for the inserting of the first root of the tree the inserting function works correctly and the first root was created successfully
but Once I assign root to current and the while loop to search for a parent then insert the new value on it, I come up with the NameError :/
Here is the implementation of my code using python:
class Node:
def __init__(self, value) :
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self):
self.root = None
def insert(self, value):
if root is None:
root == Node(value)
current = root
while(True):
if(value < current.value):
if current.left:
current.left = Node(value)
break
current = current.left
else:
if current.right:
current.right = Node(value)
break
current = current.right
if __name__ == '__main__':
tree = BST()
tree.insert(10)
tree.insert(5)
tree.insert(6)
print("Tree Inserted Successfully")
Thank you
I am trying to insert a new value in my binary search tree, so there is 2 scenarios:
if the BST is empty (this is simple and pass correctly)
the other scenario is when we have to find the parent of this node and insert its value, for that i go with while(true) and assigning a new variable current to root to keep track of current parent while traversing the tree with loop
The issues:
root should be self.root.
== is not an assignment. It should be =
you should exit the function after setting the root, and not continue with the rest of the function:
if self.root is None:
self.root = Node(value) # Assign!
return # don't continue
The conditions in the if statements that you have in the while loop, should be testing the opposite. When you don't have a left child, then you should attach a new node there, not when there is already a node there:
if(value < current.value):
if not current.left: # Opposite condition
current.left = Node(value)
break
current = current.left
else:
if not current.right: # Opposite condition
current.right = Node(value)
break
current = current.right
All code:
class Node:
def __init__(self, value) :
self.value = value
self.left = None
self.right = None
class BST:
def __init__(self):
self.root = None
def insert(self, value):
if self.root is None: # root is an attribute, not a variable
self.root = Node(value) # Assign!
return # Don't continue
current = self.root
while(True):
if(value < current.value):
if not current.left: # Opposite condition
current.left = Node(value)
break
current = current.left
else:
if not current.right: # Opposite condition
current.right = Node(value)
break
current = current.right
if __name__ == '__main__':
tree = BST()
tree.insert(10)
tree.insert(5)
tree.insert(6)
print("Tree Inserted Successfully")
print(tree.root.left.right.value) # Should output: 6

How can I run this Height of a BST tree function

can someone help me out with this? I implemented a binary search tree data structure in python and I wrote a BST_height() function to calculate the height of the tree. But when I ran my code, It gave me an error saying 'self is not defined'. I know why the error is showing up but can you suggest some other way to run the BST_height function with the root node
class Node:
def __init__(self, data=None):
self.data = data
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self):
self.root = Node()
def display(self):
print('''
{}
/ \\
{} {}
/ \\ / \\
{} {} {} {}
BINARY TREE
'''.format(tree.root.data, tree.root.left.data, tree.root.right.data, tree.root.left.left.data, tree.root.right.right.data, tree.root.left.right.data, tree.root.right.left.data))
def checkRoot(self):
if self.root.data != None:
return 'Root node exists'
else:
return 'Root node doesn\'t exists'
def insert(self, data):
newNode = Node(data)
if self.root.data == None:
# creating the root node
self.root = newNode
else:
self.insertNode(data, self.root)
def insertNode(self, data, curNode):
if data < curNode.data:
if curNode.left == None:
curNode.left = Node(data)
else:
self.insertNode(data, curNode.left)
elif data > curNode.data:
if curNode.right == None:
curNode.right = Node(data)
else:
self.insertNode(data, curNode.right)
else:
print('The value already exists ha ha')# funny
def BST_height(self, node):
if node == None:
return -1
leftHeight = height(node.left)
rightHeight = height(node.right)
return max(leftHeight, rightHeight) + 1
tree = BinarySearchTree()
tree.insert(30)# root node
tree.insert(24)
tree.insert(45)
tree.insert(90)
tree.insert(18)
tree.insert(28)
tree.insert(40)
tree.display()
# getting an error here
# I know self.root can\'t be used outside the class but can you suggest some other way tree.BST_height(self.root)
There are 2 problems with the code:
Self is something you use inside of class functions. Outside you can simply use the object variable. like so:
tree.BST_height(tree.root)
BST_height function has a small error in it. It calls height instead of self.BST_height:
def BST_height(self, node):
if node == None:
return -1
leftHeight = self.BST_height(node.left)
rightHeight = self.BST_height(node.right)
return max(leftHeight, rightHeight) + 1
You might want to read this for clarity on the whole self topic.

BST insertion function in Python

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)

Walk through nodes in linked list python

I'm set to do a binary tree search like the one here. I have a problem to set the nodes correctly.
The problem:
When a new node should be created, the root node seems to be overwriten. First time
Bintree.put(newValue)
is called a new node is created at the Bintree.root. The second time, the root node seems to be overwriten in the functioncall Bintree.put(newValue).
Does these lines below change the root node when it is executed?
node = root
node = node.left # Left is a node below node
node = Node()
The lines below is the code for my program.
# Node for binary tree
class Node():
def __init__(self):
self.data = None
self.left = None
self.right = None
class Bintree:
def __init__(self):
self.root = None
def put(self, newvalue):
'''Sends the new value into the correct position in the Bintree
:param newvalue: The data that's sent to storage'''
self.root = push(self.root, newvalue)
def push(root, value):
# This function puts the value in the correct position in the bintree
# Not to be used by user.
node = root
while node is not None:
if node.data < value:
node = node.left
else:
node = node.right
node = Node()
node.value = value
return node
Yeah you're right I screwed it up a little bit.
class Node():
def init(self):
self.data = None
self.left = None
self.right = None
class Bintree:
def init(self):
self.root = None
def put(self, newvalue):
'''Sends the new value into the correct position in the Bintree
:param newvalue: The data that's sent to storage'''
if self.root is None:
self.root = Node()
self.root.data = newvalue
else:
self.push(self.root, newvalue)
def push(self, node, value):
# This function puts the value in the correct position in the bintree
# Not to be used by user.
if value < node.data:
if node.left is not None:
self.push(node.left,value)
else:
node.left = Node()
node.left.data = value
else:
if node.right is not None:
self.push(node.right,value)
else:
node.right = Node()
node.right.data = value
I did it from scratch with recursive. It's simpler.
Of course it didn't work because in your first attempt you always set root to none and in the second you only update root all the time (my bad)

Categories

Resources