class BinarySearchTree: # The code in the book has a bug in delete_key when the to-be-deleted # node is the root: it tries to examine its parent, which doesn't exist. # To solve this, we make the root the "leftChild" of the BinarySearchTree # object. def __init__(self): self.leftChild = None self.size = 0 def put(self, key, val): if self.leftChild: self.size += self.leftChild.put(key, val) else: self.leftChild = TreeNode(key, val, self) self.size = 1 def __setitem__(self, k, v): # supports T[k] = v self.put(k, v) def get(self, key): if self.leftChild: return self.leftChild.get(key) else: return None def __getitem__(self, key): # supports v = T[k] return self.get(key) def has_key(self, key): return self.leftChild.get(key) != None def __contains__(self, key): # supports k in T return self.has_key(key) def length(self): return self.size def __len__(self): # supports len(T) return self.length() def delete_key(self, key): if self.size > 1: self.leftChild.delete_key(key) self.size = self.size-1 elif self.leftChild.key == key: self.leftChild = None self.size = 0 else: raise KeyError(key) def __delitem__(self, key): # supports del T[k] self.delete_key(key) def __iter__(self): # supports for k in T if self.leftChild: for k in self.leftChild: yield k def __str__(self): if self.leftChild: return str(self.leftChild) return "" class TreeNode: def __init__(self, key, val, parent=None, left=None, right=None): self.key = key self.payload = val self.leftChild = left self.rightChild = right self.parent = parent def put(self, key, val): # return 1 if inserted; 0 if already present if key == self.key: payload = val return 0 elif key < self.key: if self.leftChild: return self.leftChild.put(key, val) else: self.leftChild = TreeNode(key, val, self) return 1 else: if self.rightChild: return self.rightChild.put(key, val) else: self.rightChild = TreeNode(key, val, self) return 1 def get(self, key): if key == self.key: return self.payload elif key < self.key: if self.leftChild: return self.leftChild.get(key) else: return None else: # key > self.key: if self.rightChild: return self.rightChild.get(key) else: return None def findSuccessor(self): succ = None if self.rightChild: succ = self.rightChild.findMin() else: if self.parent.leftChild == self: succ = self.parent else: self.parent.rightChild = None succ = self.parent.findSuccessor() self.parent.rightChild = self return succ def findMin(self): n = self while n.leftChild: n = n.leftChild return n def spliceOut(self): assert self.leftChild == None # should never be called in any other case if self.rightChild: if self == self.parent.leftChild: self.parent.leftChild = self.rightChild else: self.parent.rightChild = self.rightChild else: # no children if self == self.parent.leftChild: self.parent.leftChild = None else: self.parent.rightchild = None def delete_key(self, key): if self.key == key: # do the removal if not (self.leftChild or self.rightChild): # no children if self == self.parent.leftChild: self.parent.leftChild = None else: self.parent.rightChild = None elif (self.leftChild or self.rightChild) and \ (not (self.leftChild and self.rightChild)): # exactly one child if self.leftChild: if self == self.parent.leftChild: self.parent.leftChild = self.leftChild else: self.parent.rightChild = self.leftChild else: if self == self.parent.leftChild: self.parent.leftChild = self.rightChild else: self.parent.rightChild = self.rightChild else: # replace self with successor succ = self.findSuccessor() succ.spliceOut() if self == self.parent.leftChild: self.parent.leftChild = succ else: self.parent.rightChild = succ succ.leftChild = self.leftChild succ.rightChild = self.rightChild else: # continue looking if key < self.key: if self.leftChild: self.leftChild.delete_key(key) else: raise KeyError(key) else: if self.rightChild: self.rightChild.delete_key(key) else: raise KeyError(key) def __iter__(self): if self.leftChild: for elem in self.leftChild: yield elem yield self.key if self.rightChild: for elem in self.rightChild: yield elem def __str__(self): rtn = "" if self.leftChild: rtn += "<" + str(self.leftChild) + ">" rtn += str(self.key) if self.rightChild: rtn += "<" + str(self.rightChild) + ">" return rtn T = None def makeT(): global T T = BinarySearchTree() T[17] = True T[5] = True T[35] = True T[2] = True T[11] = True T[29] = True T[38] = True T[9] = True T[16] = True T[7] = True T[8] = True