Check whether the given value is in the binary search tree - python

This is the code I was given and I need to make changes to it. The function looks for the value in the given BST and returns True if target is in the tree. Here's the code:
def member_prim(tnode, target):
"""
Purpose:
Check if target is stored in the binary search tree.
Pre-Conditions:
:param tnode: a treenode with the BST property
:param target: a value
Post-Conditions:
none
Return
:return: True if target is in the tree
"""
if tnode is None:
return False
elif target < tnode.data:
right = tnode.right
return member_prim(right, target)
else:
tnode.right = tnode.left
return member_prim(tnode.right, target)
I made few changes to the code and here's what I did:
if tnode is None:
return False
elif tnode.data is not target:
return False
elif target > tnode.data:
right = tnode.right
return member_prim(right, target)
else:
tnode.right = tnode.left
return member_prim(tnode.right, target)
Still it throws Attribute Error, saying object 'treenode' has no attribute 'data'.
Here's treenode class:
class treenode(object):
def __init__(self, data, left=None, right=None):
"""
Purpose:
Create a new treenode for the given data.
Pre-conditions:
data: Any data value to be stored in the treenode
left, right: Another treenode (or None, by default)
Post-condition:
none
"""
self.data = data
self.left = left
self.right = right
Please let me know where I went wrong and how can I fix it.

class treenode(object):
def __init__(self, data, left=None, right=None):
"""
Purpose:
Create a new treenode for the given data.
Pre-conditions:
data: Any data value to be stored in the treenode
left, right: Another treenode (or None, by default)
Post-condition:
none
"""
self.data = data
self.left = left
self.right = right
def trav(root, target):
if not root:
return False
if root.data == target:
return True
if root.data > target:
return trav(root.left, target)
if root.data < target:
return trav(root.right, target)
This code will find you the if the target value is present or not.

Related

Same tree verification through recursive tree traversal

I've prepared a recursive tree-traversal based solution to the "same tree" problem. However, I'm encountering an error on use cases involving None values. Why is my approach incorrect and how should I be altered to handle the use case?
class Solution(object):
def traversal(self,root):
visited = []
if root:
if root.left:
visited.extend(self.traversal(root.left))
visited.append(root.val)
if root.right:
visited.extend(self.traversal(root.right))
return visited
def isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
p_path = self.traversal(p)
q_path = self.traversal(q)
print(p_path, q_path)
return p_path == q_path
Use case: input([1,1][1,null,1]), output(true), stdout([1,1], [1,1])
Two different trees can have the same in-order traversal, but different structure, so it's not sufficient to completely rely on "traversal" in your code.
Hint: trees are only the same if they have the same root and (recursively) the same left subtree and (recursively) the same right subtree.
Gave up on the recursive attempt, but an iterative one worked.
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def isSameTree(self, p, q):
"""
:type p: TreeNode
:type q: TreeNode
:rtype: bool
"""
stack = [(p,q)]
while stack:
p_curr, q_curr = stack.pop()
# both p and q exist
if p_curr and q_curr:
# validity check
if p_curr.val != q_curr.val:
return False
# left check
if p_curr.left and q_curr.left:
stack.append((p_curr.left, q_curr.left))
elif p_curr.left and not q_curr.left:
return False
elif not p_curr.left and q_curr.left:
return False
# right check
if p_curr.right and q_curr.right:
stack.append((p_curr.right, q_curr.right))
elif p_curr.right and not q_curr.right:
return False
elif not p_curr.right and q_curr.right:
return False
elif p_curr:
# only p exists, invalid
return False
elif q_curr:
# only q exists, invalid
return False
return True

Why I am seeing None data after deleting the smallest or largest item from Binary Search Tree?

I have a binary search tree. I have written basic insert, delete, traversal of the full tree and find its maximum and minimum node of the tree but I have trouble with finding maximum and minimum node after deleting the minimum or the maximum node.
This function deletes a specific node:
def deleteNode(self,val):
if self.data:
if self.data > val:
self.left.deleteNode(val)
elif self.data < val:
self.right.deleteNode(val)
else:
if self.left is None:
self.data = self.right
return True
elif self.right is None:
self.data = self.left
return True
else:
dltNode = self
dltNode.data = self.data
largest = self.left.findMax()
dltNode.data = largest
dltNode.left.deleteNode(largest)
return True
This function finds the minimum node:
def findMin(self):
if self.data:
if self.left is None:
return self.data
else:
return self.left.findMin()
And this is for the maximum node:
def findMax(self):
if self.data:
if self.right is None:
return self.data
else:
return self.right.findMax()
findMin and findMax functions work fine without deleting any node.
If I ever call then after deleting the minimum and maximum node they will return None, whether they were supposed to return only integer node data. Here is the screenshot of my output:
It should print 34 instead of None.
Here is my full code
There are a few issues in deleteNode
if self.data should not be there: this would mean you cannot delete a node with value 0 from the tree. A similar problem exists in other methods (findMin, findMax, insert, ...).
self.left.deleteNode(val) is executed without checking first that self.left is not None. The same is true for self.right.deleteNode(val)
self.data = self.right assigns a Node reference to a data attribute (which is supposed to be a number).
The function sometimes returns nothing (None) or True. Because of the recursive nature, the original caller of the method will get None. This is not consistent.
The function cannot deal with deleting the root Node, as the caller will keep using the root node reference (t or t2 in your example code).
To solve these issues, you should either create a separate Tree class, or agree that deleteNode returns the root node of the tree, which could be a different root than the root on which the call was made (when the root node was deleted), or even None when that was the last node of the tree.
Here is how that would look:
def deleteNode(self,val):
if self.data > val:
if self.left:
self.left = self.left.deleteNode(val)
elif self.data < val:
if self.right:
self.right = self.right.deleteNode(val)
else:
if self.left is None:
return self.right
elif self.right is None:
return self.left
else:
largest = self.left.findMax()
self.data = largest
self.left = self.left.deleteNode(largest)
return self
To do it right, you would need to use the return value from this method, for example:
t1 = t1.deleteNode(34)
NB: In some methods you check whether self.data is None. I understand this is some special condition for indicating that the root node is not really a node, and should be considered an empty tree, but this is not a nice pattern. Instead, an empty tree should be just None, or you should define another Tree class which has a root attribute which can be None.

How can I sum all nodes under a given value in binary search tree?

My homework needs me to sum all numbers under the given value in a BST. However, I had no idea how to do it. Appreciate for any help.
class BinarySearchTree:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def search(self, find_data):
if self.data == find_data:
return self
elif find_data < self.data and self.left != None:
return self.left.search(find_data)
elif find_data > self.data and self.right != None:
return self.right.search(find_data)
else:
return None
def get_left(self):
return self.left
def get_right(self):
return self.right
def set_left(self, tree):
self.left = tree
def set_right(self, tree):
self.right = tree
def set_data(self, data):
self.data = data
def get_data(self):
return self.data
def create_new_bst(lst):
#creates a new tree with root node 55, and then inserts all the
#remaining values in order into the BST
def sum_beneath(t, value):
# don't know how to do
t = create_new_bst([55, 24, 8, 51, 25, 72, 78])
result = sum_beneath(t, 72)
print('Sum beneath 72 =', result)# should show 'Sum beneath 72 = 78'
I'm very new to BST so I really have no idea on how to start and do this question.
def insert(self, new_data):#can I just call this function in 'create_new_bst'?
if self.data:
if new_data < self.data:
if self.left is None:
self.left = BinarySearchTree(new_data)
else:
self.left.insert(new_data)
elif new_data > self.data:
if self.right is None:
self.right = BinarySearchTree(new_data)
else:
self.right.insert(new_data)
else:
self.data = data
Ok, as this is an exercise, I won't fill everything, but I will try to give you an idea of how it should be done:
You need to create your tree, in a simple way you can do this:
def create_new_bst(lst):
tree = BinarySearchTree(tree[0])
# And then, using the insert method, which is correct, add your nodes in the tree
return tree
First, you need to find Your subtree with the root 72
# Replace the pass with the appropriate code
def find_subtree(tree, value):
if value == tree.data: # This is found yeah !
pass
if value > tree.data: # Ok, this is not our data, we should look recursively in one of the children (I will not tell you which one). Maybe we can use find_subtree reccursively?
pass
if value < tree.data: # Same as above, but maybe we should look in the other child
pass
raise ValueError("Not found value " + str(value)) # Nothing has been found.
Now, you found the tree with my_tree = find_subtree(t, 72), you should just sum the left tree (if it exists) and the right tree (if it exists)
def sum_beneath(t, value):
my_tree = find_subtree(t, value)
s = 0
if my_tree.left is not None:
s += my_tree.left.sum_tree()
if my_tree.right is not None:
s += my_tree.right.sum_tree()
return s
Let's define the sum_tree method (in the class)! :)
def sum_tree(self):
ans = self.data
# Add the left sum reccursively
# Add the right sum reccursively
return ans
I hope this will help you to understand the concept of BST. If you need help do not hesitate to comment
It's quite an interesting problem to find the sum of nodes under a specific value, we can think of this of something like searching and transversing problem, there can be various ways to do this, but I can think of this something like-
Doing a binary search for the node.
Doing an (In-order, Post-Order or Pre-order) transversal, and saving the results of the returned nodes' values i.e. summing them up.
the big O time complexity I can think of should be something like-
for an nth node in the BST, log(n) should be the search time, then for the transversal (In-order, Post-Order or Pre-order), it should be m-n, where (m is the total number of nodes)
therefore, the total will be, (log(n) + m - n) ~ O(M).

Find if all nodes in BST are greater than a item

I have been working on trying to implement the function all_bigger below but I am not sure if there are flaws in my logic. To my understanding, BST's are organized having the smallest values on the left side so I would only need to check the left side of the BST. Is there a better way of writing this or is my code incorrect?
class BSTNode:
"""A node is a BST """
def __init__(self: 'BSTNode', item, left, right):
self.item, self.left, self.right = item, left, right
def all_bigger(self, value):
"""
>>> bst = BSTNode(5, BSTNode(4), BSTNode(6))
>>> all_bigger(bst, 2)
True
"""
while self.left:
if self.left > value:
self.value = self.left:
else:
return False
return True
Your code is almost correct, with some minor bugs. Corrected code:
class BSTNode:
"""A node is a BST """
def __init__(self, item, left = None, right = None):
self.item, self.left, self.right = item, left, right
def all_bigger(self, value):
"""
>>> bst = BSTNode(5, BSTNode(4), BSTNode(6))
>>> all_bigger(bst, 2)
True
"""
root = self
while(root!=None):
if root.item > value:
root = root.left
else:
return False
return True
bst = BSTNode(5, BSTNode(4,BSTNode(1, None, None),None), BSTNode(6,None,None)) # Returns False
print(bst.all_bigger(2))
IIUC your question is to see if all the nodes in the BST are bigger than a certain value.
A simple way to do is to find the node with the minimum value in the BST and compare it with the other value. The smallest node is going to be the left-most node.
A typical BST node looks like this
# A binary tree node
class Node:
# Constructor to create a new node
def __init__(self, key):
self.data = key
self.left = None
self.right = None
And yes, you're right. The tree does not need to be searched fully, ie, the right subtrees can be skipped. This is how you find the node with the minimum value.
def minValue(node):
current = node
# loop down to find the lefmost leaf
while(current.left is not None):
current = current.left
return current.data
This can be slightly tweaked to solve your problem
def all_bigger(node, val):
current = node
# loop down to find the lefmost leaf
while(current.left is not None):
current = current.left
# Check if the current node value is smaller than val
if current.data < val:
return False
return True
You need to update the node after every comparison. Kindly check the below code:
class BSTNode:
"""A node is a BST """
def __init__(self: 'BSTNode', item, left, right):
self.item, self.left, self.right = item, left, right
def all_bigger(self, value):
"""
>>> bst = BSTNode(5, BSTNode(4), BSTNode(6))
>>> all_bigger(bst, 2)
True
"""
while self.item:
if self.left > value:
self.item = self.left:
else:
return False
return True
All values in a subtree are greater than X if and only if
The value in the node is greater than X, and
All values in its left subtree (if it exists) are greater than X
Assuming an empty tree is None:
def all_bigger(self, value):
return self.value > value and self.left and self.left.all_bigger(value)

How to determine if a Binary Tree node is a Left or Right child?

I have a simple Tree data structure, however, I would like to implement two methods named isLeftChild and isRightChild.
The problem is I am having a very hard time understanding trees. The concept and general process has not fully been grasped.
Here is my simple tree so far:
class Node(object):
''' A tree node. '''
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def isLeftChild(self):
''' Returns True if the node is a left child, else False. '''
pass
def isRightChild(self):
''' Returns True if the node is a right child, else False. '''
pass
def insert(self, data):
''' Populate the tree. '''
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)
else:
self.data = data
def printTree(self):
''' Display the tree. '''
if self.left:
self.left.printTree()
print self.data
if self.right:
self.right.printTree()
def main():
root = Node(8)
root.insert(2)
root.printTree()
main()
How can I have a node determine if it is a left child or a right child (without reference to its data)?
I am not sure what I need to add to my tree in order to determine this.
Use a parent attribute and test if the memory reference if the parent's right or left is the same as the child's reference in memory. You're going to need a parent attribute to traverse the tree anyway.
return self is self.parent.left # in the isLeftChild

Categories