binary search tree missing 1 required positional argument: - python

Trying to construct the Binary search tree here
class Node:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BSTree():
def __init__(self, rootdata):
self.root = Node(rootdata)
def insert(self, data, cur_node):
if data < cur_node.data:
if cur_node.left == None:
cur_node.left = Node(data)
else:
self.insert(data, cur_node.left)
elif data > cur_node.data:
if cur_node.right == None:
cur_node.right = Node(data)
else:
self.insert(data, cur_node.right)
else:
print("Duplicate value!")
def find(self, data, cur_node):
if data < cur_node.data and cur_node.left:
return self.find(data, cur_node.left)
elif data > cur_node.data and cur_node.right:
return self.find(data, cur_node.right)
if data == cur_node.data:
return True
return False
def PreOder(self,root):
if root == None:
pass
else:
print(root.data)
self.PreOrder(root.left)
self.PreOrder(root.right)
a = BSTree()
a.insert(3)
a.insert(4)
a.insert(7)
a.insert(34)
a.insert(24)
a.insert(2)
a.insert(49)
print(a.find(3))
print(a.PreOrder(3))
I am getting an error message: init() missing 1 required positional argument: 'rootdata'
How to fix and print the binary search tree?
Also, what I have up there is just the random number I am try to construct the binary tree out from the list I have
mylist = [1,3,2,4,12,14,23,43,23,44,34,43]

Here is a working and properly formatted update of your code. Not sure what it's doing exactly, but it should give you some clues to solve your task. Maybe you could use an IDE like Visual Studio Code or Pycharm to help you out with python specific stuff.
class Node:
# Constructor to create a new node
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BSTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def insert(self, data, cur_node):
if data < cur_node.data:
if cur_node.left is None:
cur_node.left = Node(data)
else:
self.insert(data, cur_node.left)
elif data > cur_node.data:
if cur_node.right is None:
cur_node.right = Node(data)
else:
self.insert(data, cur_node.right)
else:
print("Duplicate value!")
def find(self, data, cur_node):
if data < cur_node.data and cur_node.left:
return self.find(data, cur_node.left)
elif data > cur_node.data and cur_node.right:
return self.find(data, cur_node.right)
if data == cur_node.data:
return True
return False
def pre_order(self, root):
if root is None:
pass
else:
print(root.data)
self.pre_order(root.left)
self.pre_order(root.right)
a = BSTree(3)
a.insert(4, a.root)
a.insert(7, a.root)
a.insert(34, a.root)
a.insert(24, a.root)
a.insert(2, a.root)
a.insert(49, a.root)
print(a.find(3, a.root),)
print(a.pre_order(a.root))

Some issues:
Your BSTree constructor does not create an emtpy tree, but a tree with already one node, and so it expects the data for that node as argument. This design is not good, because it does not support the concept of an empty tree. So the constructor should change and just set self.root to None.
insert takes also more arguments than expected: it does so because it uses that argument for implementing recursion. There are many ways to make it work, but I prefer that the recursive call is made in OOP-style, i.e. the recursive insert method should be placed in the Node class, and act on self instead of on an extra argument. The insert method on the BSTree class can then just be a wrapper around that method, where it gets called on the root node.
A similar issue occurs with find. The solution can be the same as for insert.
And again, the issue occurs also with preOrder: it takes a node as argument. Same solution as discussed above. I would also avoid printing in a method. Instead yield the values.
So here is how that would look:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def insert(self, data):
if data < self.data:
if not self.left:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if not self.right:
self.right = Node(data)
else:
self.right.insert(data)
else:
print("Duplicate value!")
def find(self, data):
if data < self.data and self.left:
return self.left.find(data)
elif data > self.data and self.right:
return self.right.find(data)
return data == self.data
def preOrder(self):
yield self.data
if self.left:
yield from self.left.preOrder()
if self.right:
yield from self.right.preOrder()
class BSTree():
def __init__(self):
self.root = None
def insert(self, data):
if not self.root:
self.root = Node(data)
else:
self.root.insert(data)
def find(self, data):
return self.root.find(data) if self.root else False
def preOrder(self):
if self.root:
yield from self.root.preOrder()
a = BSTree()
a.insert(3)
a.insert(4)
a.insert(7)
a.insert(34)
a.insert(24)
a.insert(2)
a.insert(49)
print(a.find(3))
print(*a.preOrder()) # With * we splash every yielded value as argument to print().

Related

Is it a good idea to have functions whose sole purpose it is to call another function? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 11 months ago.
Improve this question
I wrote code for a Tree traversal. In the Binary_tree class, I wrote three methods: __Inorder, __Postorder, and __Preorder, for tree traversal; and I wrote three other methods to call them and pass in self.root as a parameter so that I don't have to pass it manually every time I want to traverse.
Code:
class Node():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class Binary_Tree():
def __init__(self):
self.root = None
def insert(self, data):
new_node = Node(data)
if self.root == None:
self.root = new_node
else:
current_node = self.root
while True:
if data > current_node.data:
if not current_node.right:
current_node.right = new_node
return
else:
current_node = current_node.right
else:
if not current_node.left:
current_node.left = new_node
return
else:
current_node = current_node.left
def inorder_traversal(self):
return self.__Inorder(self.root)
def postorder_traversal(self):
return self.__Postorder(self.root)
def preorder_traversal(self):
return self.__Preorder(self.root)
def __Inorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
self.__Inorder(current_node.left, visited_node)
visited_node.append(current_node.data)
self.__Inorder(current_node.right, visited_node)
return visited_node
def __Postorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
self.__Postorder(current_node.left, visited_node)
self.__Postorder(current_node.right, visited_node)
visited_node.append(current_node.data)
return visited_node
def __Preorder(self, current_node, visited_node = None):
if visited_node is None:
visited_node = []
if current_node:
visited_node.append(current_node.data)
self.__Preorder(current_node.left, visited_node)
self.__Preorder(current_node.right, visited_node)
return visited_node
I showed this code to a guy I know and he said "there is no point in writing a function whose sole instruction is to call another function" and it is bad code writing. So, is it true? If yes, then how should I do it?
Your friend is wrong.
Your function (like inorder_traversal) is not just calling another function: it also disallows the caller to pass any arguments, which are none of their business (current_node, visited_node). And this makes it a good decision to have a clean public method, while the underscored "private" functions deal with implementation details that are reflected in their function parameters.
Not your question, but I do see some room for avoiding code repetition, as your base functions have very similar code. Also you could consider creating generators for them instead of populating lists. You could also consider moving those private methods to the Node class.
For example:
class Node():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def traverse(self, order=0):
if order == -1:
yield self.data
if self.left:
yield from self.left.traverse(order)
if order == 0:
yield self.data
if self.right:
yield from self.right.traverse(order)
if order == 1:
yield self.data
class Binary_Tree():
def __init__(self):
self.root = None
def insert(self, data):
new_node = Node(data)
if self.root == None:
self.root = new_node
else:
current_node = self.root
while True:
if data > current_node.data:
if not current_node.right:
current_node.right = new_node
return
else:
current_node = current_node.right
else:
if not current_node.left:
current_node.left = new_node
return
else:
current_node = current_node.left
def preorder_traversal(self):
if self.root:
return self.root.traverse(-1)
def inorder_traversal(self):
if self.root:
return self.root.traverse(0)
def postorder_traversal(self):
if self.root:
return self.root.traverse(1)
# Demo run
tree = Binary_Tree()
for data in (4,2,3,1,6,5,7):
tree.insert(data)
print(*tree.inorder_traversal())

How to find if a value exist within a Binary Tree: True or False (Python3)

I am trying to write a code which the output returns either True or False, if the value exists within the Binary Tree.
Here is my attempt:
Defining a class called Node:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
Defining a class called BinaryTree + LOOKUP function:
class BinaryTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def LOOKUP(self, lookupval):
if lookupval < self.data:
if (self.left == None):
self.left.LOOKUP(lookupval)
return False
elif lookupval > self.data:
if (self.right == None):
self.right.LOOKUP(lookupval)
return False
else:
return True
The rest, inputting values into the Binary Tree:
Tree = BinaryTree(24)
Tree.root.left = Node(11)
Tree.root.left.left = Node(199)
Tree.root.left.right = Node(167)
Tree.root.right = Node(2)
Tree.root.right.right = Node(8)
print(Tree.LOOKUP(11))
print(Tree.LOOKUP(13))
However, I keep getting the error 'BinaryTree' object has no attribute 'data'..
I understand there will be some errors in the definition of the function LOOKUP,
but is there any chance that I could keep this format and still return the outputs:
True
False
Thank you,
The issues in your code are:
you're trying to reference self.right (should be self.root.right instead - because we're not on the Node instance)
the nested if check are wrong. You should recursively check the left/right tree if NOT None or return False there.
Do something like this:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BinaryTree:
def __init__(self, rootdata):
self.root = Node(rootdata)
def LOOKUP(self, lookupval):
if lookupval < self.root.data:
if self.root.left:
return BinaryTree(self.root.left.data).LOOKUP(lookupval) # recursively check the left tree
else:
return False # can't go any further- so return false
elif lookupval > self.root.data:
if self.root.right:
return BinaryTree(self.root.right.data).LOOKUP(lookupval)
else:
return False
else:
return True
Tree = BinaryTree(24)
Tree.root.left = Node(11)
Tree.root.left.left = Node(199)
Tree.root.left.right = Node(167)
Tree.root.right = Node(2)
Tree.root.right.right = Node(8)
print(Tree.LOOKUP(11))
print(Tree.LOOKUP(13))
output:
True
False

How to get the length of a tree in python binary search

class Node:
def __init__(self,data=None):
self.data=data
self.left_child=None
self.right_child=None
self.parent=None
self.root = None
class BinarySearchTree:
def __init__(self):
self.root=None
def add(self, data):
if self.root == None:
self.root = Node(data)
else:
self.add_helper(data, self.root)
def add_helper(self, data, cur_node):
if data < cur_node.data:
if cur_node.left_child == None:
cur_node.left_child = Node(data)
cur_node.left_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.left_child)
elif data > cur_node.data:
if cur_node.right_child == None:
cur_node.right_child = Node(data)
cur_node.right_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.right_child)
else:
print("data already in tree!")
def __len__(self):
if self.root is None:
return 0
else:
return (self.__len__(self.left_child) + 1 +self. __len__(self.right_child))
So i am trying to return the length of the binary search tree list, so i tried using the len method for my binary search tree class. However, this is not working correctly. I need it to be able to not take in any parameters, and just return an integer for the length of the binary search tree list. What am i missing and what am i doing wrong here?
You will need a helper function that takes a Node argument. Then do the recursion on the left and right of the node.
def __len__(self):
return self.tree_len(self.root)
def tree_len(self, node):
if node is None:
return 0
else:
return 1 + max(self.tree_len(node.right_child), self.tree_len(node.left_child))

Python binary tree

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)

How to call a class method using an instance of a different class in Python?

I am a trying to implement a binary tree using two classes - Node and Binary Tree. When I am inserting the nodes (left or right), I am using the methods insert_left_node and insert_right_node which are class BinaryTree's methods, but I am also using class Node to create a node. After every node insertion, the current object is returned.
Now, how do I call class BinaryTree's insertion methods using the returned object - current. E.g. In the second last line of the code, statement n3 = n1.insert_left_node(33) fails with AttributeError: 'Node' object has no attribute 'insert_left_node'
I need an alternative way to achieve this.
Code:
class Node(object):
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BinaryTree(object):
def __init__(self, root=None):
self.root = Node(root)
def insert_left_node(self, data):
if not self.root:
self.root = Node(data)
else:
current = self.root
while True:
if current.left:
current = current.left
else:
current.left = Node(data)
break
return current
def insert_right_node(self, data):
if not self.root:
self.root = Node(data)
else:
current = self.root
while True:
if current.right:
current = current.right
else:
current.right = Node(data)
break
return current
if __name__ == '__main__':
r = BinaryTree(34) # root
n1 = r.insert_left_node(22)
n2 = r.insert_right_node(45)
n3 = n1.insert_left_node(33) # Fails
print n3
Your request literally doesn't make any sense. To achieve what you want you should just add the needed methods to the class you want to use. Try something similar to the following:
class Node(object):
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def insert_left_node(self, data):
self.left = Node(data)
def insert_right_node(self, data):
self.right = Node(data)

Categories