Binary Search Tree
The tricky one is deletion. The idea is the following:
Case #1: node is a leaf:
if parent:
link parent.left or parent.right to None
else:
delete root key
Case #2: node has one child:
find the successor
if parent:
link parent with successor
else:
root node key = successor.key
set root child to None
Case #3: node has two children:
find successor (smallest node bigger than node)
set node.key = successor.key
(successor's parent).left/right = successor.right
And here we go with the code.
def preorder(tree):
if tree:
print tree.key,
preorder(tree.left)
preorder(tree.right)
class Node(object):
def __init__(self, value):
self.key = value
self.left = None
self.right = None
def insert(self, value):
if value < self.key:
if self.left is None:
self.left = Node(value)
else:
self.left.insert(value)
elif value > self.key:
if self.right is None:
self.right = Node(value)
else:
self.right.insert(value)
# the straightforward version
def lookup(self, value):
if self.key == value:
return self
elif value < self.key:
if self.left is None:
return None
return self.left.lookup(value)
else:
if self.right is None:
return None
return self.right.lookup(value)
# returns both node and parent node; used for delete()
def lookupParent(self, value, parent=None):
if self.key == value:
return self, parent
elif value < self.key:
if self.left is None:
return None, None
return self.left.lookupParent(value, self)
elif value > self.key:
if self.right is None:
return None, None
return self.right.lookupParent(value, self)
# recursive version
def findMin(self):
if self.left is None:
return self
return self.left.findMin()
# iterative version
def findMax(self):
maxNode = self
while maxNode.right is not None:
maxNode = maxNode.right
return maxNode
def delete(self, value):
node, parent = self.lookupParent(value)
# key does not exist
if node is None:
return
# CASE #1, node is a leaf
if node.right is None and node.left is None:
if parent:
if parent.left is node:
parent.left = None
else:
parent.right = None
# key is in the root node
else:
self.key = None
# CASE #2, node has one child
elif node.right is None or node.left is None:
# find the successor
if node.left:
successor = node.left
else:
successor = node.right
# if there is a parent, link parent with successor
if parent:
if parent.left is node:
parent.left = successor
else:
parent.right = successor
# key is in the root node
else:
node.key = successor.key
node.left = None
node.right = None
# CASE #3, node has two childs
else:
parent = node
successor = node.right
while successor.left:
parent = successor
successor = successor.left
node.key = successor.key
# fix successor's parent's child
if parent.left == successor:
parent.left = successor.right
else:
parent.right = successor.right
root = Node(10)
root.insert(3)
root.insert(44)
root.insert(1)
root.insert(5)
root.insert(4)
root.insert(6)
root.insert(99)
preorder(root)
print
root.delete(3)
print
preorder(root)