12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#coding:utf-8
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Author:  Mozman
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Purpose: treemixin provides top level functions for binary trees
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Created: 03.05.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 .walker import Walker
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from .treeslice import TreeSlice
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TreeMixin(object):
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Abstract-Base-Class for the pure Python Trees: BinaryTree, AVLTree and RBTree
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Mixin-Class for the Cython based Trees: FastBinaryTree, FastAVLTree, FastRBTree
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    The TreeMixin Class
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ===================
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    T has to implement following properties
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ---------------------------------------
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    count -- get node count
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    T has to implement following methods
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ------------------------------------
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    get_walker(...)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        get a tree walker object, provides methods to traverse the tree see walker.py
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    insert(...)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        insert(key, value) <==> T[key] = value, insert key into T
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remove(...)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        remove(key) <==> del T[key], remove key from T
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    clear(...)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        T.clear() -> None.  Remove all items from T.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Methods defined here
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    --------------------
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __contains__(k) -> True if T has a key k, else False, O(log(n))
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __delitem__(y) <==> del T[y], del T[s:e], O(log(n))
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __getitem__(y) <==> T[y], T[s:e], O(log(n))
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __iter__() <==> iter(T)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __len__() <==> len(T), O(1)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __max__() <==> max(T), get max item (k,v) of T, O(log(n))
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __min__() <==> min(T), get min item (k,v) of T, O(log(n))
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __and__(other) <==> T & other, intersection
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __or__(other) <==> T | other, union
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __sub__(other) <==> T - other, difference
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __xor__(other) <==> T ^ other, symmetric_difference
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __repr__() <==> repr(T)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __setitem__(k, v) <==> T[k] = v, O(log(n))
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * clear() -> None, Remove all items from T, , O(n)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * copy() -> a shallow copy of T, O(n*log(n))
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * discard(k) -> None, remove k from T, if k is present, O(log(n))
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * get(k[,d]) -> T[k] if k in T, else d, O(log(n))
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * is_empty() -> True if len(T) == 0, O(1)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * items([reverse]) -> generator for (k, v) items of T, O(n)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * keys([reverse]) -> generator for keys of T, O(n)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * values([reverse]) -> generator for values of  T, O(n)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * pop(k[,d]) -> v, remove specified key and return the corresponding value, O(log(n))
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple, O(log(n))
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * setdefault(k[,d]) -> T.get(k, d), also set T[k]=d if k not in T, O(log(n))
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * update(E) -> None.  Update T from dict/iterable E, O(E*log(n))
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * foreach(f, [order]) -> visit all nodes of tree and call f(k, v) for each node, O(n)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    slicing by keys
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * itemslice(s, e) -> generator for (k, v) items of T for s <= key < e, O(n)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * keyslice(s, e) -> generator for keys of T for s <= key < e, O(n)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * valueslice(s, e) -> generator for values of T for s <= key < e, O(n)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * T[s:e] -> TreeSlice object, with keys in range s <= key < e, O(n)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * del T[s:e] -> remove items by key slicing, for s <= key < e, O(n)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if 's' is None or T[:e] TreeSlice/iterator starts with value of min_key()
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if 'e' is None or T[s:] TreeSlice/iterator ends with value of max_key()
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    T[:] is a TreeSlice which represents the whole tree.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TreeSlice is a tree wrapper with range check, and contains no references
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to objects, deleting objects in the associated tree also deletes the object
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    in the TreeSlice.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * TreeSlice[k] -> get value for key k, raises KeyError if k not exists in range s:e
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * TreeSlice[s1:e1] -> TreeSlice object, with keys in range s1 <= key < e1
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      * new lower bound is max(s, s1)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      * new upper bound is min(e, e1)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TreeSlice methods:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * items() -> generator for (k, v) items of T, O(n)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * keys() -> generator for keys of T, O(n)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * values() -> generator for values of  T, O(n)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __iter__ <==> keys()
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __repr__ <==> repr(T)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * __contains__(key)-> True if TreeSlice has a key k, else False, O(log(n))
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    prev/succ operations
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * prev_item(key) -> get (k, v) pair, where k is predecessor to key, O(log(n))
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * prev_key(key) -> k, get the predecessor of key, O(log(n))
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * succ_item(key) -> get (k,v) pair as a 2-tuple, where k is successor to key, O(log(n))
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * succ_key(key) -> k, get the successor of key, O(log(n))
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * floor_item(key) -> get (k, v) pair, where k is the greatest key less than or equal to key, O(log(n))
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * floor_key(key) -> k, get the greatest key less than or equal to key, O(log(n))
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * ceiling_item(key) -> get (k, v) pair, where k is the smallest key greater than or equal to key, O(log(n))
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * ceiling_key(key) -> k, get the smallest key greater than or equal to key, O(log(n))
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Heap methods
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * max_item() -> get largest (key, value) pair of T, O(log(n))
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * max_key() -> get largest key of T, O(log(n))
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * min_item() -> get smallest (key, value) pair of T, O(log(n))
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * min_key() -> get smallest key of T, O(log(n))
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * pop_min() -> (k, v), remove item with minimum key, O(log(n))
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * pop_max() -> (k, v), remove item with maximum key, O(log(n))
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * nlargest(i[,pop]) -> get list of i largest items (k, v), O(i*log(n))
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * nsmallest(i[,pop]) -> get list of i smallest items (k, v), O(i*log(n))
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Set methods (using frozenset)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * intersection(t1, t2, ...) -> Tree with keys *common* to all trees
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * union(t1, t2, ...) -> Tree with keys from *either* trees
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * difference(t1, t2, ...) -> Tree with keys in T but not any of t1, t2, ...
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * symmetric_difference(t1) -> Tree with keys in either T and t1  but not both
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * issubset(S) -> True if every element in T is in S
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * issuperset(S) -> True if every element in S is in T
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * isdisjoint(S) ->  True if T has a null intersection with S
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Classmethods
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    * fromkeys(S[,v]) -> New tree with keys from S and values equal to v.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def get_walker(self):
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return Walker(self)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __repr__(self):
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__repr__(...) <==> repr(x) """
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tpl = "%s({%s})" % (self.__class__.__name__, '%s')
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return tpl % ", ".join( ("%r: %r" % item for item in self.items()) )
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def copy(self):
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.copy() -> get a shallow copy of T. """
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tree = self.__class__()
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.foreach(tree.insert, order=-1)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return tree
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __copy__ = copy
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __contains__(self, key):
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ k in T -> True if T has a key k, else False """
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.get_value(key)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return True
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except KeyError:
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return False
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __len__(self):
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__len__() <==> len(x) """
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.count
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __min__(self):
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__min__() <==> min(x) """
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.min_item()
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __max__(self):
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__max__() <==> max(x) """
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.max_item()
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __and__(self, other):
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__and__(other) <==> self & other """
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.intersection(other)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __or__(self, other):
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__or__(other) <==> self | other """
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.union(other)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __sub__(self, other):
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__sub__(other) <==> self - other """
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.difference(other)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __xor__(self, other):
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__xor__(other) <==> self ^ other """
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.symmetric_difference(other)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def discard(self, key):
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.discard(k) -> None, remove k from T, if k is present """
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.remove(key)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except KeyError:
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            pass
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __del__(self):
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.clear()
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def is_empty(self):
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.is_empty() -> False if T contains any items else True"""
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.count == 0
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def keys(self, reverse=False):
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.iterkeys([reverse]) -> an iterator over the keys of T, in ascending
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        order if reverse is True, iterate in descending order, reverse defaults
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        to False
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return ( item[0] for item in self.items(reverse) )
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __iter__ = keys
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __reversed__(self):
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.keys(reverse=True)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def values(self, reverse=False):
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.values([reverse]) -> an iterator over the values of T, in ascending order
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if reverse is True, iterate in descending order, reverse defaults to False
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return ( item[1] for item in self.items(reverse) )
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def items(self, reverse=False):
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.items([reverse]) -> an iterator over the (key, value) items of T,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        in ascending order if reverse is True, iterate in descending order,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reverse defaults to False
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.is_empty():
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return []
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        def default_iterator(node):
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            direction = 1 if reverse else 0
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            other = 1 - direction
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            go_down = True
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            while True:
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if node.has_child(direction) and go_down:
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    node.push()
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    node.down(direction)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                else:
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    yield node.item
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    if node.has_child(other):
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        node.down(other)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        go_down = True
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    else:
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        if node.stack_is_empty():
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            return  # all done
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        node.pop()
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        go_down = False
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        treewalker = self.get_walker()
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:  # specialized iterators
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if reverse:
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return treewalker.iter_items_backward()
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            else:
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return treewalker.iter_items_forward()
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except AttributeError:
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return default_iterator(treewalker)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __getitem__(self, key):
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__getitem__(y) <==> x[y] """
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if isinstance(key, slice):
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return TreeSlice(self, key.start, key.stop)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return self.get_value(key)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __setitem__(self, key, value):
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__setitem__(i, y) <==> x[i]=y """
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if isinstance(key, slice):
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise ValueError('setslice is not supported')
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.insert(key, value)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __delitem__(self, key):
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.__delitem__(y) <==> del x[y] """
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if isinstance(key, slice):
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.delitems(self.keyslice(key.start, key.stop))
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.remove(key)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def delitems(self, keys):
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.delitems(keys) -> remove all items by keys
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # convert generator to a set, because the content of the
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # tree will be modified!
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for key in frozenset(keys):
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.remove(key)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def keyslice(self, startkey, endkey):
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.keyslice(startkey, endkey) -> key iterator:
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        startkey <= key < endkey.
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return ( item[0] for item in self.itemslice(startkey, endkey) )
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def itemslice(self, startkey, endkey):
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.itemslice(s, e) -> item iterator: s <= key < e.
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if s is None: start with min element -> T[:e]
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if e is None: end with max element -> T[s:]
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        T[:] -> all items
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.is_empty():
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if startkey is None:
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            # no lower bound
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            can_go_left = lambda: node.has_left() and visit_left
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            # don't visit subtrees without keys in search range
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            can_go_left = lambda: node.key > startkey and node.has_left() and visit_left
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if endkey is None:
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            # no upper bound
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            can_go_right = lambda: node.has_right()
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            # don't visit subtrees without keys in search range
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            can_go_right = lambda: node.key < endkey and node.has_right()
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (startkey, endkey) == (None, None):
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            key_in_range = lambda: True
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        elif startkey is None:
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            key_in_range = lambda: node.key < endkey
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        elif endkey is None:
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            key_in_range = lambda: node.key >= startkey
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            key_in_range = lambda: startkey <= node.key < endkey
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        node = self.get_walker()
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        visit_left = True
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        while True:
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if can_go_left():
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.push()
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.go_left()
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            else:
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if key_in_range():
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    yield node.item
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if can_go_right():
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    node.go_right()
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    visit_left = True
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                else:
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    if node.stack_is_empty():
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        return
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    node.pop()
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    # left side is already done
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    visit_left = False
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def valueslice(self, startkey, endkey):
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.valueslice(startkey, endkey) -> value iterator:
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        startkey <= key < endkey.
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return ( item[1] for item in self.itemslice(startkey, endkey) )
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def get_value(self, key):
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        node = self.root
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        while node is not None:
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if key == node.key:
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return node.value
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            elif key < node.key:
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node = node.left
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            else:
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node = node.right
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        raise KeyError(str(key))
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __getstate__(self):
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return dict(self.items())
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __setstate__(self, state):
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # note for myself: this is called like __init__, so don't use clear()
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # to remove existing data!
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self._root = None
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self._count = 0
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.update(state)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def setdefault(self, key, default=None):
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.setdefault(k[,d]) -> T.get(k,d), also set T[k]=d if k not in T """
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return self.get_value(key)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except KeyError:
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.insert(key, default)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return default
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def update(self, *args):
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.update(E) -> None. Update T from E : for (k, v) in E: T[k] = v """
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for items in args:
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            try:
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                generator = items.items()
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            except AttributeError:
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                generator = iter(items)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            for key, value in generator:
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                self.insert(key, value)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @classmethod
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def fromkeys(cls, iterable, value=None):
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.fromkeys(S[,v]) -> New tree with keys from S and values equal to v.
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        v defaults to None.
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tree = cls()
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for key in iterable:
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            tree.insert(key, value)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return tree
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def get(self, key, default=None):
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.get(k[,d]) -> T[k] if k in T, else d.  d defaults to None. """
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return self.get_value(key)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except KeyError:
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return default
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def pop(self, key, *args):
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.pop(k[,d]) -> v, remove specified key and return the corresponding value
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        If key is not found, d is returned if given, otherwise KeyError is raised
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if len(args) > 1:
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise TypeError("pop expected at most 2 arguments, got %d" % (1 + len(args)))
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try:
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            value = self.get_value(key)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self.remove(key)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return value
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        except KeyError:
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if len(args) == 0:
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                raise
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            else:
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return args[0]
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def popitem(self):
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.popitem() -> (k, v), remove and return some (key, value) pair as a
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        2-tuple; but raise KeyError if T is empty
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.is_empty():
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise KeyError("popitem(): tree is empty")
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker = self.get_walker()
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker.goto_leaf()
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result = walker.item
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.remove(walker.key)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return result
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def foreach(self, func, order=0):
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Visit all tree nodes and process key, value.
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        parm func: function(key, value)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        param int order: inorder = 0, preorder = -1, postorder = +1
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        def _traverse():
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if order == -1:
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                func(node.key, node.value)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if node.has_left():
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.push()
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.go_left()
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                _traverse()
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.pop()
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if order == 0:
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                func(node.key, node.value)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if node.has_right():
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.push()
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.go_right()
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                _traverse()
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                node.pop()
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if order == +1:
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                func(node.key, node.value)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        node = self.get_walker()
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        _traverse()
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def min_item(self):
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get item with min key of tree, raises ValueError if tree is empty. """
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise ValueError("Tree is empty")
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        node = self._root
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        while node.left is not None:
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            node = node.left
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (node.key, node.value)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def pop_min(self):
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.pop_min() -> (k, v), remove item with minimum key, raise ValueError
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if T is empty.
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        item = self.min_item()
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.remove(item[0])
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return item
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def min_key(self):
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get min key of tree, raises ValueError if tree is empty. """
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.min_item()
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def prev_item(self, key):
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get predecessor (k,v) pair of key, raises KeyError if key is min key
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        or key does not exist.
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise KeyError("Tree is empty")
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker = self.get_walker()
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return walker.prev_item(key)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def succ_item(self, key):
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get successor (k,v) pair of key, raises KeyError if key is max key
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        or key does not exist.
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise KeyError("Tree is empty")
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker = self.get_walker()
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return walker.succ_item(key)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def prev_key(self, key):
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get predecessor to key, raises KeyError if key is min key
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        or key does not exist.
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.prev_item(key)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def succ_key(self, key):
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get successor to key, raises KeyError if key is max key
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        or key does not exist.
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.succ_item(key)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def floor_item(self, key):
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get the element (k,v) pair associated with the greatest key less
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        than or equal to the given key, raises KeyError if there is no such key.
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise KeyError("Tree is empty")
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker = self.get_walker()
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return walker.floor_item(key)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def floor_key(self, key):
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get the greatest key less than or equal to the given key, raises
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        KeyError if there is no such key.
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.floor_item(key)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def ceiling_item(self, key):
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get the element (k,v) pair associated with the smallest key greater
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        than or equal to the given key, raises KeyError if there is no such key.
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise KeyError("Tree is empty")
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        walker = self.get_walker()
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return walker.ceiling_item(key)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def ceiling_key(self, key):
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get the smallest key greater than or equal to the given key, raises
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        KeyError if there is no such key.
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.ceiling_item(key)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def max_item(self):
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get item with max key of tree, raises ValueError if tree is empty. """
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if self.count == 0:
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            raise ValueError("Tree is empty")
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        node = self._root
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        while node.right is not None:
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            node = node.right
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (node.key, node.value)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def pop_max(self):
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.pop_max() -> (k, v), remove item with maximum key, raise ValueError
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if T is empty.
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        item = self.max_item()
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.remove(item[0])
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return item
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def max_key(self):
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ Get max key of tree, raises ValueError if tree is empty. """
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        key, value = self.max_item()
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return key
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def nsmallest(self, n, pop=False):
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.nsmallest(n) -> get list of n smallest items (k, v).
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        If pop is True, remove items from T.
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if pop:
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return [self.pop_min() for _ in range(min(len(self), n))]
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            items = self.items()
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return  [ next(items) for _ in range(min(len(self), n)) ]
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def nlargest(self, n, pop=False):
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ T.nlargest(n) -> get list of n largest items (k, v).
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        If pop is True remove items from T.
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if pop:
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return [self.pop_max() for _ in range(min(len(self), n))]
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            items = self.items(reverse=True)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return [ next(items) for _ in range(min(len(self), n)) ]
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def intersection(self, *trees):
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.intersection(t1, t2, ...) -> Tree, with keys *common* to all trees
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sets = _build_sets(trees)
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rkeys = thiskeys.intersection(*sets)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.__class__( ((key, self.get(key)) for key in rkeys) )
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def union(self, *trees):
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.union(t1, t2, ...) -> Tree with keys from *either* trees
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rkeys = thiskeys.union(*_build_sets(trees))
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.__class__( ((key, self.get(key)) for key in rkeys) )
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def difference(self, *trees):
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.difference(t1, t2, ...) -> Tree with keys in T but not any of t1,
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        t2, ...
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rkeys = thiskeys.difference(*_build_sets(trees))
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.__class__( ((key, self.get(key)) for key in rkeys) )
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def symmetric_difference(self, tree):
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.symmetric_difference(t1) -> Tree with keys in either T and t1  but
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        not both
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rkeys = thiskeys.symmetric_difference(frozenset(tree.keys()))
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return self.__class__( ((key, self.get(key)) for key in rkeys) )
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def issubset(self, tree):
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.issubset(tree) -> True if every element in x is in tree """
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return thiskeys.issubset(frozenset(tree.keys()))
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def issuperset(self, tree):
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.issubset(tree) -> True if every element in tree is in x """
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return thiskeys.issuperset(frozenset(tree.keys()))
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def isdisjoint(self, tree):
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        """ x.isdisjoint(S) ->  True if x has a null intersection with tree """
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thiskeys = frozenset(self.keys())
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return thiskeys.isdisjoint(frozenset(tree.keys()))
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _build_sets(trees):
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return [ frozenset(tree.keys()) for tree in trees ]
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
643