Eine mögliche Implementation wäre:
class KeyValTree(BinaryTree): """This class encapsulates a tree of key/value pairs. It's somewhat unfortunate that what we call value in the BinaryNode now is the key of the key value pair. We compensate with a bit of name shuffling magic. Additional magic in here is that you can create an "empty" node that is filled in as soon as it should receive a key/value. This is mainly useful for the root node. >>> d = KeyValTree() >>> d["bla"] = "foo" >>> d["drei"] = 3 >>> d["aaa"] = 9 >>> d["bla"] 'foo' >>> d["bla"] = 10 >>> d["bla"] 10 >>> print d 9 10 3 """ def __init__(self, key=None, value=None): BinaryTree.__init__(self, key) self.nodeValue = value getKey = BinaryTree.getValue def getValue(self): return self.nodeValue def setValue(self, value): self.nodeValue = value def __cmp__(self, other): try: return cmp(self.getKey(), other.getKey()) except AttributeError: return -1 def insert(self, key, value): """inserts newNode into the tree in a position such that the property of being sorted is maintained. Unfortunately, we need to replicate some code from SortedTree -- this may be a hint that we need to refactor, now that we have the additional functionality. It would be concivable to let SortedTree.insert take a Node as well (it would then have to replace the node in case of a perfect match to make things work here). """ if self.getKey() is None: self.value = key self.setValue(value) if key<self.getKey(): setMeth, getMeth = self.setLeft, self.getLeft elif key==self.getKey(): self.setValue(value) return else: setMeth, getMeth = self.setRight, self.getRight if not getMeth() is None: self.getMeth().insert(key, value) else: setMeth(KeyValTree(key, value)) __setitem__ = insert def retrieve(self, key): """returns a the value for key if present, raises KeyError otherwise """ try: if self.getKey()>key: return self.getLeft().retrieve(key) elif key==self.getKey(): return self.getValue() else: return self.getRight().retrieve(key) except AttributeError: raise KeyError(key) __getitem__ = retrieve iterkeys = BinaryTree.__iter__ def itervalues(self): yield self.getValue() for child in [self.getLeft(), self.getRight()]: if child is not None: for val in child.itervalues(): yield val
Beachtet, dass sowohl insert als auch retrieve eigentlich nichts mehr machen müssen, nachdem sie ihren rekursiven Aufruf abgesetzt haben (in insert könnte man das noch etwas deutlicher machen, in retrieve stört die Exception-Behandlung etwas, aber das soll hier nicht kümmern). Solche Funktionen heißen endrekursiv und können vom System potenziell erheblich effizienter bearbeitet werden als rekursive Funktionen ohne diese Eigenschaft. Mehr dazu in Programmieren II – Python ist das ohnehin egal.
Wenn ihr Lust habt, implementiert doch einfach noch weitere Methoden, die ihr von Dictionaries kennt: keys, values, items (prima zum Traversieren…), has_key, iterkeys usf.