I tried to get the closest value to a target value inside a binary tree with this programme and it didn't work, although it worked well in manually (static) inserted tree !!!
def clos(self,target):
if self.root:
self._clos(self.root,target)
def _clos(self,curnode,value):
a = curnode.val
l=[]
kid = curnode.left if value < a else curnode.right
if not kid:
return a
else:
b = self._clos(kid, value)
l.extend([value-a,value-b])
return min(map(abs,l))
#print(l) for showing the None_object error
tree = Tree()
l=[1, 2, 4, 5,7,13,15,22,70]
tree.array_to_bst(l)
print(tree.clos(3))
this return :
Traceback (most recent call last):
File "C:\Users\HP\Documents\Codes\new 1.py", line 110, in <module>
print(tree.clos(3))
^^^^^^^^^^^^
File "C:\Users\HP\Documents\Codes\new 1.py", line 91, in clos
self._clos(self.root,target)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\HP\Documents\Codes\new 1.py", line 102, in _clos
l.extend([_value-a,_value-b])
~~~~~~^~
TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'
The error occurs because your function does not always execute a return
statement. You have put a return
statement in comments, and instead print a result, but this means that None
is returned to the caller, and that caller will assign that None
to b
, and then the expression value-b
triggers the error you see.
Note that the clos
method also lacks a return
statement and so the caller of clos
will always get None
.
I did not quite understand which algorithm you had in mind, as even returning min(map(abs, l))
is not useful to the caller. You need to return an actual value that is in the tree, not a difference.
A common way to implement this is to pass a "window" to the recursive call, and have that window shrink every time you make a step further down the tree. When the end of the path is encountered, choose one of the two boundary values of that window, depending on which is closer to the given value.
Here is an implementation:
def clos(self, target):
if self.root:
return self._clos(self.root, target, float('-inf'), float('inf'))
def _clos(self, curnode, value, low, high):
if not curnode:
# Determine which of the two is closest to value (low or high)
if value - low < high - value:
return low
else:
return high
if value < curnode.val:
return self._clos(curnode.left, value, low, curnode.val)
else:
return self._clos(curnode.right, value, curnode.val, high)