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)
Related
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
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()
I'm learning binary search trees right now and made one myself. The problem with my tree is that the traverse() method doesn't print the largest value ('15' in the code pasted below), unless it is the first value to be inserted.
I've also tried getMaxValue() function and it also doesn't return the expected value, instead gives the second largest value.
This lead to me thinking that the problem must be in insert() function somewhere, but it's been an hour and i can't find a fix or what I did wrong.
class Node(object):
def __init__(self,data):
self.data = data
self.leftChild = None
self.rightChild = None
class BinarySearchTree(object):
def __init__(self):
self.root = None
#Parent function of insert
def insert(self,data):
if not self.root:
self.root = Node(data)
else:
self.insertNode(data,self.root)
# O(log n) if the tree is balanced!!!!
# thats why AVL and RBT are needed!
#Child function of insert
def insertNode(self,data,node):
if data < node.data:
# check if there is already a left child, if it is not null then we call insertNode recursively and insert a node as its child
if node.leftChild:
self.insertNode(data,node.leftChild)
# if there is no left child then we instantiate it, and make a left child, same stuff happening for right child
else:
node.leftChild = Node(data)
else:
if node.rightChild:
self.insertNode(data, node.rightChild)
else:
self.rightChild = Node(data)
#Parent function of getminvalue
def getMinValue(self):
if self.root:
return self.getMin(self.root)
#Child function of getminvalue
def getMin(self,node):
#if there is a left child
if node.leftChild:
#go to left child recursively
return self.getMin(node.leftChild)
return node.data
#Parent function of getMaxValue
def getMaxValue(self):
if self.root:
return self.getMax(self.root)
#Child function of getmaxValue
def getMax(self, node):
if node.rightChild:
return self.getMax(node.rightChild)
return node.data
#Parent function of traverse
def traverse(self):
if self.root:
self.traverseInOrder(self.root)
#Child function of traverseinOrder
def traverseInOrder(self,node):
if node.leftChild:
self.traverseInOrder(node.leftChild)
print("%s " % node.data)
if node.rightChild:
self.traverseInOrder(node.rightChild)
#Inputs
bst = BinarySearchTree()
bst.insert(10)
bst.insert(15)
bst.insert(5)
bst.insert(4)
bst.insert(3)
print(bst.traverse())
The expected result is
3
4
5
10
15
but I'm getting
3
4
5
10
None
fixed:
will soon edit with details
class Node(object):
def __init__(self,data):
self.data = data
self.leftChild = None
self.rightChild = None
class BinarySearchTree(object):
def __init__(self):
self.root = None
#Parent function of insert
def insert(self,data):
if not self.root:
self.root = Node(data)
else:
self.insertNode(data,self.root)
# O(log n) if the tree is balanced!!!!
# thats why AVL and RBT are needed!
#Child function of insert
def insertNode(self,data,node):
if data < node.data:
# check if there is already a left child, if it is not null then we call insertNode recursively and insert a node as its child
if node.leftChild:
self.insertNode(data,node.leftChild)
# if there is no left child then we instantiate it, and make a left child, same stuff happening for right child
else:
node.leftChild = Node(data)
else:
if node.rightChild:
self.insertNode(data, node.rightChild)
else:
node.rightChild = Node(data)
#Parent function of getminvalue
def getMinValue(self):
if self.root:
return self.getMin(self.root)
#Child function of getminvalue
def getMin(self,node):
#if there is a left child
if node.leftChild:
#go to left child recursively
return self.getMin(node.leftChild)
return node.data
#Parent function of getMaxValue
def getMaxValue(self):
if self.root:
return self.getMax(self.root)
#Child function of getmaxValue
def getMax(self, node):
if node.rightChild:
return self.getMax(node.rightChild)
return node.data
#Parent function of traverse
def traverse(self):
if self.root:
self.traverseInOrder(self.root)
#Child function of traverseinOrder
def traverseInOrder(self,node):
if node.leftChild:
self.traverseInOrder(node.leftChild)
print("%s " % node.data)
if node.rightChild:
self.traverseInOrder(node.rightChild)
#Inputs
bst = BinarySearchTree()
bst.insert(10)
bst.insert(15)
bst.insert(5)
bst.insert(4)
bst.insert(3)
bst.traverse()
I stepped through the code with a debugger (which I recommend you do, it is very helpful), and saw this:
as you can see, node with data 10 has no right child, whereas self has a root with data 10 and rightChild with data 15.
that made me look at the line that insert a new right child, there you had mistakenly wrote: self.rightChild = Node(data) instead of node.rightChild = Node(data) (like you correctly do with the left child)
I'm scratching my head for an hour.
I implemented binary tree in-order traversal using the iterator & stack.
class Node:
def __init__(self, val, left, right):
self.val = val
self.left = left
self.right = right
class BTIterator:
def __init__(self, root):
self.stack = [] # Use a list as a stack by using pop() & append()
self.root = root
self.leftmost = None
def Run(self):
node = self.root
while (node.left != None):
self.stack.append(node)
node = node.left
print(self.stack)
self.leftmost = node
print(self.leftmost.val)
while (self.Next(node) != None):
node = self.Next(node)
print(node.val)
def Next(self, node):
if (node.left != None):
while (node.left != None):
self.stack.append(node.left)
node = node.left
return node
elif (node.right != None):
node = node.right
while (node.left != None):
self.stack.append(node)
node = node.left
return node
else:
if self.stack != []:
node = self.stack.pop()
node.left = None
return node
if __name__ == '__main__':
# Let's construct the tree.
n12 = Node(12, None, None)
n11 = Node(11, None, n12)
n9 = Node(9, None, None)
n10 = Node(10, n9, n11)
n15 = Node(15, None, None)
n13 = Node(13, n10, n15)
n5 = Node(5, None, None)
n3 = Node(3, None, n5)
n7 = Node(7, n3, n13)
bti = BTIterator(n7)
bti.Run()
I also ran above implementation on IDE. From debugging, I clearly see def Next(self, node) returns n7. However once node = self.Next(node) line gets the n7, it turns n7 into None. Why?!
I think this must be a python syntax that I do not know.
Any pointer will be appreciated.
in your implementation, there are three problems I want to point out:
the main problem is your implemtation in Next is incorrect. Because inorder traversal is left->root->right, if (node.left != None): part is correct, but here:
elif (node.right != None):
node = node.right
while (node.left != None):
self.stack.append(node)
node = node.left
return node
you should return node itself first before deal with right child.
else:
if self.stack != []:
node = self.stack.pop()
node.left = None
return node
and you should not only pop when node is leaf, you should push every node in stack, and pop every Next.
you can not put Next in both while condition and block, because it will call twice.
while (self.Next(node) != None):
node = self.Next(node)
!= None in if (node.left != None): is not needed in python, you can just use if node.left:
because Next has many problems, so I have to rewrited Next, here is the version I edited based on your code, and I have commented in details:
class BTIterator:
def __init__(self, root):
self.stack = [] # Use a list as a stack by using pop() & append()
self.root = root
def Run(self):
# find the left most node, which means then first node
node = self.root
while node.left:
self.stack.append(node)
node = node.left
# start from left most node
while node:
print(node.val)
node = self.Next(node)
def Next(self, node):
# find right node, if it is none, it's ok, we will deal with it afterwards
node = node.right
# reach the end
if not self.stack and not node:
return None
# push left child iteratively
while node:
self.stack.append(node)
node = node.left
# this is next node we want
return self.stack.pop()
Hope that helps you, and comment if you have further questions. : )
I have been struggling with this problem for a while and I am a Python beginner when it comes to BST, so I would appreciate some help. I am dynamically adding elements from an (unsorted) array into BST. That part is fine, I know how to do that. The next step, proved to be impossible with my current skill set. As I am adding elements to the tree, I need to be able to find current rank of any element in the tree. I know there are subtleties in this problem, so I would need help to at least find the number of nodes that are below the given node in BST. For example, in this case, node 15 has nodes 10,5 and 13 below it, so the function will return 3. Here is my existing code [this is a problem from Cracking the coding interview, chapter 11]
class Node:
"""docstring for Node"""
def __init__(self, data):
self.data = data
self.left=None
self.right=None
self.numLeftChildren=0
self.numRightChildren=0
class BSTree:
def __init__(self):
self.root = None
def addNode(self, data):
return Node(data)
def insert(self, root, data):
if root == None:
return self.addNode(data)
else:
if data <= root.data:
root.numLeftChildren+=1
root.left = self.insert(root.left, data)
else:
root.numRightChildren+=1
root.right = self.insert(root.right, data)
return root
def getRankOfNumber(self,root,x):
if root==None:
return 0
else:
if x>root.data :
return self.getRankOfNumber(root.right,x)+root.numLeftChildren+1
elif root.data==x:
return root.numLeftChildren
else:
return self.getRankOfNumber(root.left,x)
BTree=BSTree()
root=BTree.addNode(20)
BTree.insert(root,25)
BTree.insert(root,15)
BTree.insert(root,10)
BTree.insert(root,5)
BTree.insert(root,13)
BTree.insert(root,23)
You can go by this approach:
1. Have 2 more fields in each node numLeftChildren and numRightChildren.
2. Initialize both of them to 0 when you create a new node.
3. At the time of insertion, you make a comparison if the newly added node's
key is less than root's key than you increment, root's numLeftChildren and
call recursion on root's left child with the new node.
4. Do Same thing if new node's key is greater than root's key.
Now, come back to your original problem, You have to find out the number of children in left subtree. Just find out that node in O(logN) time and just print the numLeftChildren
Time Complexity: O(logN)
PS: I have added another field numRightChildren which you can remove if you are always interested in knowing the number of nodes in left subtree only.
You could modify your BST to contain the number of nodes beneath each node.
Or you could iterate over a traditional BST from least to greatest, counting as you go, and stop counting when you find a node of the required value.
You could simplify the code by using just instances of the Node class, as your BSTree instance operates on the root node anyway. Another optimization could be to not represent duplicate values as separate nodes, but instead use a counter of occurrences of the key:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.num_left_children = 0
self.occurrences = 1
def insert(self, data):
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
self.num_left_children += 1
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.occurrences += 1
def get_rank(self, data):
if data < self.data:
return self.left.get_rank(data)
elif data > self.data:
return (self.occurrences + self.num_left_children +
self.right.get_rank(data))
else:
return self.num_left_children
Demo:
root = Node(20)
root.insert(25)
root.insert(15)
root.insert(10)
root.insert(10)
root.insert(5)
root.insert(13)
root.insert(23)
print(root.get_rank(15)) # 4
You can use the below function to find the number of the nodes in the tree (including the root).
def countNodes(self, root):
if root == None:
return 0
else
return (1 + countNodes(root.left) + countNodes(root.right));
To find the number of nodes that lie below root, subtract 1 from the value returned by the function. I think this will help get you started on the problem.
Your code will look like:
class Node:
"""docstring for Node"""
def init(self, data):
self.data = data
self.left=None
self.right=None
self.depth=0
class BSTree:
def init(self):
self.root = None
def addNode(self, data):
return Node(data)
def insert(self, root, data):
if root == None:
return self.addNode(data)
else:
if data <= root.data:
root.left = self.insert(root.left, data)
else:
root.right = self.insert(root.right, data)
return root
BTree=BSTree()
root=BTree.addNode(20)
BTree.insert(root,25)
BTree.insert(root,15)
BTree.insert(root,10)
BTree.insert(root,5)
BTree.insert(root,13)
BTree.insert(root,23)
BTree.insert(root,23)
numLeft = countNodes(root->left);
numRight = countNodes(root->right);
numChildren = numLeft + numRight;