Python binary tree - python

I have implemented a simple tree and I have this problem. When I try to search for a node and it exists it returns None even though it runs the print at the if statement in lookup method. It runs ok when I lookup for the root node. All the rest nodes return None. Could someone explain why ?
class Node():
def __init__(self,data):
self.right = None
self.left = None
self.data = data
def insert(self,data):
if self.data == data:
print "this item exists"
elif self.data > data:
if self.left == None:
self.left = Node(data)
else:
self.left.insert(data)
else:
if self.right == None:
self.right = Node(data)
else:
self.right.insert(data)
def print_nodes(self):
if self.left:
self.left.print_nodes()
print self.data
if self.right:
self.right.print_nodes()
def lookup(self,data):
if self.data == data:
print 'exists'
return 1
elif self.data > data:
if self.left != None:
self.left.lookup(data)
else:
return -1
elif self.data < data:
if self.right != None:
self.right.lookup(data)
else:
return -1
def delete(self,data):
if self.lookup(data)== -1:
print "doesnot exists"
else:
if (not self.left) and (not self.right):
self.data = None
root = Node(5)
#root.insert(3)
root.insert(3)
root.insert(2)
root.insert(6)
root.insert(61)
root.insert(62)
root.insert(63)
x = root.lookup(3)
print x

when the item is not exists in the root, you call to its sons lookup() functions without returning their value, so even if the code finds the data somewhere in the tree, you get None value instead of the result (1/-1)
Replace this lines:
self.left.lookup(data)
...
self.right.lookup(data)
with the lines:
return self.left.lookup(data)
...
return self.right.lookup(data)

Related

Binary search tree - why does it not work without the "return" statement

When I want to search for a name which is in the tree, without the return statement I only get None but why?
See code comment #<----
class Tree:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def child(self, data):
if self.data == data:
return
if self.data < data:
if self.right:
self.right.child(data)
else:
self.right = Tree(data)
elif self.data > data:
if self.left:
self.left.child(data)
else:
self.left = Tree(data)
def search(self, elem):
if self.data == elem:
return True
if self.data < elem:
if self.right:
return self.right.search(elem) #<----
else:
self.right = False
elif self.data > elem:
if self.left:
return self.left.search(elem) #<----
else:
self.left = False
Without return, you ignore the result of the subtree search and fall through to the end of the method, at which point you return None implicitly.
You also need to return False when the appropriate subtree is empty, not set the subtree reference to False.
def search(self, elem):
if self.data == elem:
# Found it!
return True
elif self.data < elem:
# If it exists, it's in the right subtree
return self.right is not None and self.right.search(elem)
else:
# If it exists, it's in the left subtree
return self.left is not None and self.left.search(elem)

i wrote a simple program for returning level of a node in tree using python but it returns none

class Node:
def __init__(self,data):
self.data=data
self.left=self.right=None
def insert(self,data):
if self.data:
if data<self.data:
if self.left is None:
self.left=Node(data)
else:
self.left.insert(data)
elif data>self.data:
if self.right is None:
self.right=Node(data)
else:
self.right.insert(data)
def level(self,data,l):
if data<self.data:
if self.left is None:
return -1
self.left.level(data,l+1)
elif data>self.data:
if self.right is None:
return -1
self.right.level(data,l+1)
elif self.data==data:
print(l)
l=[8,7,6,5,10]
root=Node(l.pop(0))
for i in l:
root.insert(i)
pre(root)
l=root.level(10,1)
print(l)
expected out put is 2
but returns None
class Node:
def __init__(self,data):
self.data=data
self.left=self.right=None
def insert(self,data):
if self.data:
if data<self.data:
if self.left is None:
self.left=Node(data)
else:
self.left.insert(data)
elif data>self.data:
if self.right is None:
self.right=Node(data)
else:
self.right.insert(data)
def level(self,data,l):
if data == self.data:
level = l
else:
if data<self.data:
if self.left is None:
return -1
level = self.left.level(data,l+1)
elif data>self.data:
if self.right is None:
return -1
level = self.right.level(data,l+1)
return level
l=[8,7,6,5,10]
root=Node(l.pop(0))
for i in l:
root.insert(i)
print(root.level(8,1))
print(root.level(7,1))
print(root.level(6,1))
print(root.level(5,1))
print(root.level(10,1))
Your function should return something and also need to update level.

Cofusing about lookup node with binary tree

I build a binary tree with python code, now I could print it in order with testTree.printInorder(testTree.root). I have tried to lookup some node ,and the function findNode doesn't work anymore . print testTree.findNode(testTree.root,20) whatever I put in just return None.
class TreeNode:
def __init__(self, value):
self.left = None;
self.right = None;
self.data = value;
class Tree:
def __init__(self):
self.root = None
def addNode(self,node,value):
if node == None:
self.root = TreeNode(value)
else:
if value < node.data:
if node.left == None:
node.left = TreeNode(value)
else:
self.addNode(node.left,value)
else:
if node.right == None:
node.right = TreeNode(value)
else:
self.addNode(node.right,value)
def printInorder(self,node):
if node != None:
self.printInorder(node.left)
print node.data
self.printInorder(node.right)
def findNode(self,node,value):
if self.root != None:
if value == node.data:
return node.data
elif value < node.data and node.left != None:
self.findNode(node.left,value)
elif value > node.data and node.right != None:
self.findNode(node.right,value)
else:
return None
testTree = Tree()
testTree.addNode(testTree.root, 200)
testTree.addNode(testTree.root, 300)
testTree.addNode(testTree.root, 100)
testTree.addNode(testTree.root, 30)
testTree.addNode(testTree.root, 20)
#testTree.printInorder(testTree.root)
print testTree.findNode(testTree.root,20)
Any function without an explicit return will return None.
You have not returned the recursive calls within findNode. So, here.
if value == node.data:
return node.data
elif value < node.data and node.left != None:
return self.findNode(node.left,value)
elif value > node.data and node.right != None:
return self.findNode(node.right,value)
Now, I can't help but thinking this is a bit noisy. You'll always start adding from the root, yes?
testTree.addNode(testTree.root, 200)
You could rather do this
testTree.addNode(200)
And to do that, you basically implement your methods on the TreeNode class instead. So, for the addNode.
You could also "return up" from the recursion, rather than "pass down" the nodes as parameters.
class TreeNode:
def __init__(self, value):
self.left = None
self.right = None
self.data = value
def addNode(self,value):
if self.data == None: # Ideally, should never end-up here
self.data = value
else:
if value < self.data:
if self.left == None:
self.left = TreeNode(value)
else:
self.left = self.left.addNode(value)
else:
if self.right == None:
self.right = TreeNode(value)
else:
self.right = self.right.addNode(value)
return self # Return back up the recursion
Then, in the Tree class, just delegate the addNode responsibility to the root
class Tree:
def __init__(self):
self.root = None
def addNode(self,value):
if self.root == None:
self.root = TreeNode(value)
else:
self.root = self.root.addNode(value)
When you recurse to children in findNode you need to return the result, otherwise the function will implicitly return None:
def findNode(self,node,value):
if self.root != None:
if value == node.data:
return node.data
elif value < node.data and node.left != None:
return self.findNode(node.left,value) # Added return
elif value > node.data and node.right != None:
return self.findNode(node.right,value) # Added return
else:
return None

Construct a Binary Tree with Preorder Traversal and store the values in a list

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)

How can I make a tree Node object display its contents when printed?

This error is occurring when we call the lookup method. Can anyone say how can it be rectified? I am unable to debug it using the available documents online. This is an implementation of a binary tree class. I know it is something related to the equivalence problem.
import deque
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def insert(self, data):
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
else:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
def lookup(self, data, parent=None):
if self.data == data:
return self, parent
if data < self.data:
if self.left is None:
return None
else:
return self.left.lookup(data, parent=self)
else:
if self.right is None:
return None
else:
return self.right.lookup(data, parent=self)
# aka bfs traversal
def level_traversal(self):
root = self
dq = deque()
dq.append(root)
while dq:
root = dq.popleft()
if root.left:
dq.append(root.left)
if root.right:
dq.append(root.right)
print (root.data)
def delete(self, data):
node, parent = self.lookup(data)
if node.children_count() == 0:
if parent.left == node:
parent.left = None
else:
parent.right = None
del node
elif node.children_count() == 1:
if node.left:
n = node.left
else:
n = node.right
if parent:
if parent.left == node:
parent.left = n
else:
parent.right = n
del node
else:
# find the successor
parent = node
successor = node.right
while successor.left:
parent = successor
successor = successor.left
node.data = successor.data
if parent.left == successor:
parent.left = successor.right
else:
parent.right = successor.right
def inorder(self):
if self.left:
self.left.inorder()
print (self.data)
if self.right:
self.right.inorder()
def preorder(self):
print (self.data)
if self.left:
self.left.preorder()
if self.right:
self.right.preorder()
def postorder(self):
if self.left:
self.left.postorder()
if self.right:
self.right.postorder()
print (self.data)
root = Node(8)
root.insert(3)
root.insert(10)
root.insert(1)
root.insert(6)
root.insert(4)
root.insert(7)
root.insert(14)
root.insert(13)
# look up
print (root.lookup(6))
# level traversal
root.level_traversal()
#mirror image
#root.mirror_image()
#root.delete(3)
#root.level_traversal()
# inorder
#root.inorder()
# pre order
#root.preorder()
# postorder
#root.postorder()
# size
#root.size()
#root.dfs()
#print root.height()
This is not an error at all. This happens because you are returning a tuple of objects from your lookup method, and this is just how objects are represented when you print them out. If you don't like this, you can overwrite the __repr__() method.
Try this in your class definition.
Definition for a binary Tree Node
class TreeNode:
def __init__(self, val = 0, left = None, right = None):
self.val = val
self.left = left
self.right = right
## print TreeNode Object
def __repr__(self) -> str:
return '[%s, %r, %r]' % (self.val, self.left, self.right)

Categories