#!/usr/bin/env python #coding:utf-8 # Author: mozman # Purpose: binary tree module # Created: 28.04.2010 # Copyright (c) 2010-2013 by Manfred Moitzi # License: MIT License from __future__ import absolute_import from .abctree import ABCTree __all__ = ['BinaryTree'] class Node(object): """Internal object, represents a tree node.""" __slots__ = ['key', 'value', 'left', 'right'] def __init__(self, key, value): self.key = key self.value = value self.left = None self.right = None def __getitem__(self, key): """N.__getitem__(key) <==> x[key], where key is 0 (left) or 1 (right).""" return self.left if key == 0 else self.right def __setitem__(self, key, value): """N.__setitem__(key, value) <==> x[key]=value, where key is 0 (left) or 1 (right).""" if key == 0: self.left = value else: self.right = value def free(self): """Set references to None.""" self.left = None self.right = None self.value = None self.key = None class BinaryTree(ABCTree): """ BinaryTree implements an unbalanced binary tree with a dict-like interface. see: http://en.wikipedia.org/wiki/Binary_tree A binary tree is a tree data structure in which each node has at most two children. BinaryTree() -> new empty tree. BinaryTree(mapping,) -> new tree initialized from a mapping BinaryTree(seq) -> new tree initialized from seq [(k1, v1), (k2, v2), ... (kn, vn)] see also abctree.ABCTree() class. """ def _new_node(self, key, value): """Create a new tree node.""" self._count += 1 return Node(key, value) def insert(self, key, value): """T.insert(key, value) <==> T[key] = value, insert key, value into tree.""" if self._root is None: self._root = self._new_node(key, value) else: parent = None direction = 0 node = self._root while True: if node is None: parent[direction] = self._new_node(key, value) break if key == node.key: node.value = value # replace value break else: parent = node direction = 0 if key <= node.key else 1 node = node[direction] def remove(self, key): """T.remove(key) <==> del T[key], remove item from tree.""" node = self._root if node is None: raise KeyError(str(key)) else: parent = None direction = 0 while True: if key == node.key: # remove node if (node.left is not None) and (node.right is not None): # find replacment node: smallest key in right-subtree parent = node direction = 1 replacement = node.right while replacement.left is not None: parent = replacement direction = 0 replacement = replacement.left parent[direction] = replacement.right #swap places node.key = replacement.key node.value = replacement.value node = replacement # delete replacement! else: down_dir = 1 if node.left is None else 0 if parent is None: # root self._root = node[down_dir] else: parent[direction] = node[down_dir] node.free() self._count -= 1 break else: direction = 0 if key < node.key else 1 parent = node node = node[direction] if node is None: raise KeyError(str(key))