Node insertion is easy, with or without a parent pointer.
...
def insert(self, val):
if val < self.val:
if self.lchild is None:
self.lchild = TreeNode(val)
else:
self.lchild.insert(val)
if val > self.val:
if self.rchild is None:
self.rchild = TreeNode(val)
else:
self.rchild.insert(val)
Traversal is also easy....
def depth_traversal(self, order="pre"):
if order == "pre":
yield self.val
if self.lchild is not None:
for v in self.lchild.depth_traversal(order=order):
yield v
if order == "in":
yield self.val
if self.rchild is not None:
for v in self.rchild.depth_traversal(order=order):
yield v
if order == "post":
yield self.val
These are simple, because you are recursing down the tree.Tree balancing is much more complicated, because logically you need to start on the bottom of the tree, each node rotation needs to update what the parent is pointing to, and the pointer to the head node may no longer be the head node.
All of these problems can be worked around. If you return the pivot node at the end of a rotation, then you can call rotations from the parents pointer.
def _rot_right(self):
pivot = self.lchild
self.lchild.rchild, self.lchild = self, self.lchild.rchild
return pivot
def _rot_left(self):
pivot = self.rchild
self.rchild.lchild, self.rchild = self, self.rchild.lchild
return pivot
>>> node.lchild = node.lchild._rot_right()
Starting at the bottom of the tree can work in the same way as post
oder traversal, where by recursing through the tree at the beginning of
your function, and stepping through logic after assures that you will
visit all the children of a node before you visit that node...
def rebalance(self, head):
if self.lchild is not None:
self.lchild.rebalance(head=head)
if self.rchild is not None:
self.rchild.rebalance(head=head)
balance = self.balance()
if balance > 1:
lbalance = self.lchild.balance()
if lbalance > 1:
self.lchild = self.lchild._rot_right()
elif lbalance < -1:
self.lchild = self.lchild._rot_left()
elif balance < -1:
rbalance = self.rchild.balance()
if rbalance > 1:
self.rchild = self.rchild._rot_right()
elif rbalance < -1:
self.rchild = self.rchild._rot_left()
Rebalancing should return the new head node, so that pointers can be reassigned elsewhere....
if head is self:
if balance > 1:
head = self._rot_right()
head = head.rebalance(head)
return head
elif balance < -1:
head = self._rot_left()
head = head.rebalance(head)
return head
return self
And there you have it. A Binary Search Tree with no parent pointer.
No comments:
Post a Comment