12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#coding:utf-8 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Author: mozman 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Purpose: binary tree module 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Created: 28.04.2010 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2010-2013 by Manfred Moitzi 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# License: MIT License 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from __future__ import absolute_import 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from .treemixin import TreeMixin 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)__all__ = ['BinaryTree'] 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Node(object): 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ Internal object, represents a treenode """ 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __slots__ = ['key', 'value', 'left', 'right'] 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, key, value): 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.key = key 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.value = value 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.left = None 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.right = None 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __getitem__(self, key): 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ x.__getitem__(key) <==> x[key], where key is 0 (left) or 1 (right) """ 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self.left if key == 0 else self.right 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __setitem__(self, key, value): 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ x.__setitem__(key, value) <==> x[key]=value, where key is 0 (left) or 1 (right) """ 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if key == 0: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.left = value 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.right = value 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def free(self): 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ Set references to None """ 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.left = None 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.right = None 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.value = None 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.key = None 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BinaryTree(TreeMixin): 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BinaryTree implements an unbalanced binary tree with a dict-like interface. 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) see: http://en.wikipedia.org/wiki/Binary_tree 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) A binary tree is a tree data structure in which each node has at most two 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) children. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BinaryTree() -> new empty tree. 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BinaryTree(mapping,) -> new tree initialized from a mapping 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BinaryTree(seq) -> new tree initialized from seq [(k1, v1), (k2, v2), ... (kn, vn)] 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) see also TreeMixin() class. 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def __init__(self, items=None): 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ x.__init__(...) initializes x; see x.__class__.__doc__ for signature """ 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._root = None 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._count = 0 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if items is not None: 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.update(items) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def clear(self): 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ T.clear() -> None. Remove all items from T. """ 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _clear(node): 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if node is not None: 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _clear(node.left) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _clear(node.right) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.free() 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _clear(self._root) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._count = 0 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._root = None 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @property 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def root(self): 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ root node of T """ 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self._root 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @property 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def count(self): 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ count of items """ 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return self._count 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def _new_node(self, key, value): 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ Create a new tree node. """ 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._count += 1 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Node(key, value) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def insert(self, key, value): 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ T.insert(key, value) <==> T[key] = value, insert key, value into Tree """ 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if self._root is None: 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._root = self._new_node(key, value) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = None 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 0 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = self._root 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while True: 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if node is None: 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent[direction] = self._new_node(key, value) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if key == node.key: 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.value = value # replace value 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = node 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 0 if key <= node.key else 1 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = node[direction] 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def remove(self, key): 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """ T.remove(key) <==> del T[key], remove item <key> from tree """ 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = self._root 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if node is None: 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise KeyError(str(key)) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = None 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 0 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while True: 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if key == node.key: 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # remove node 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (node.left is not None) and (node.right is not None): 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # find replacment node: smallest key in right-subtree 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = node 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 1 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replacement = node.right 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while replacement.left is not None: 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = replacement 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 0 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replacement = replacement.left 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent[direction] = replacement.right 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #swap places 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.key = replacement.key 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.value = replacement.value 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = replacement # delete replacement! 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) down_dir = 1 if node.left is None else 0 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if parent is None: # root 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._root = node[down_dir] 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent[direction] = node[down_dir] 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node.free() 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self._count -= 1 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else: 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction = 0 if key < node.key else 1 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent = node 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = node[direction] 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if node is None: 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise KeyError(str(key)) 154