I'm trying to implement a Binary Search Tree class. I have two classes; BSTNode
, and BST
. I try to enforce the search tree property in the setters for left
and right
:
class BSTNode(object):
def __init__(self,new):
if type(new) is BSTNode:
self._data = new.data
else:
self._data = new
self._left = None
self._right = None
@property
def data(self):
return self._data
@property
def left(self):
return self._left
@left.setter
def left(self,data):
if data is None:
self._left = None
else:
n = BSTNode(data)
if n.data >= self.data:
del n
raise ValueError("Value must be less-than parent!")
self._left = n
@property
def right(self):
return self._right
@right.setter
def right(self,data):
if data is None:
self._right = None
else:
n = BSTNode(data)
if n.data < self.data:
del n
raise ValueError("Value must be greater-than or equal-to parent!")
self._right = n
class BST(object):
def __init__(self):
self._root = None
@property
def root(self):
return self._root
@root.setter
def root(self,value):
self._root = BSTNode(value)
def binary_insert(self,list_in):
self.root = binary_insert(list_in,0,len(list_in) - 1)
Now, I am trying to implement a method binary_insert(self,list_in)
where I insert a sorted list into the tree such that the tree is balanced (using essentially binary search); however, my left and right nodes off of root
are always None
, though I assign them explicitly in the function, and I am sure my indices are correct, as I get the following to print when I run it:
> t = BST()
> list_in = [0,1,2,3,4,5,6,7,8]
> t.binary_insert(list_in)
4
1
0
2
3
6
5
7
8
Here is my function (note instance method binary_insert
above in class BST
):
def binary_insert(list_in,imin,imax):
if imax < imin:
return None
imid = int(floor((imax + imin) / 2))
n = BSTNode(list_in[imid])
print(n.data)
n.left = binary_insert(list_in,imin,imid-1)
n.right = binary_insert(list_in,imid+1,imax)
return n
I am always returning a BSTNode
, which is None
only when the input to the setter is None
, though the only node in the tree after the function runs is root
. I suspect there is something going on with the properties that I don't understand. I'd love some clarification on this.
> t = BST()
> list_in = [0,5,12]
> t.binary_insert(list_in)
5
0
12
> t.root.data
5
> t.root.left
None
> t.root.right
None
Expected:
> t.root.left.data
0
> t.root.right.data
12
The issue occurs because the following line executes after all the recursion is done and root is created as a BSTNode -
self.root = binary_insert(list_in,0,len(list_in) - 1)
That is at the end binary_insert()
returns a BSTNode
which is the root, this calls the setter
for root
, which is -
@root.setter
def root(self,value):
self._root = BSTNode(value)
This causes self._root
to be initialized with a new BSTNode
reference whose data is same as that of root returned from binary_insert()
, this calls the __init__()
for BSTNode
passing in the root
as the argument. And the __init__()
function of BSTNode
does this -
def __init__(self,new):
if type(new) is BSTNode:
self._data = new.data
else:
self._data = new
self._left = None
self._right = None
Here , you are setting self._left
to None
and self._right
to None
. So the root's left and right values are none, as you observed.
Two ways you can solve this issue, one is -
change the line where you are setting self.root
to -
def binary_insert(self,list_in):
self._root = binary_insert(list_in,0,len(list_in) - 1)
Or you can also, change the __init__()
BSTNode , such that if the type(new)
is BSTNode
, you copy over the left
and right
values from the new
BSTNode
as well. Example -
def __init__(self,new):
if type(new) is BSTNode:
self._data = new.data
self._left = new.left
self._right = new.right
else:
self._data = new
self._left = None
self._right = None
It looks like your insert method is building a tree, but it's not attaching to the root and all references to the tree are being lost.
By the way, note that your method for balancing the tree (choosing the middle of the partition of the list) only works if the list is sorted. You'll need to either sort the list beforehand or use a more general balancing scheme like an AVL tree or a Red-Black tree
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.