# 问题

Python中的二叉树查找算法模块

# 思路说明

python中的二叉树模块内容：

• BinaryTree：非平衡二叉树
• AVLTree：平衡的AVL树
• RBTree：平衡的红黑树

• FastBinaryTree
• FastAVLTree
• FastRBTree

# 安装和使用

## 安装方法

### 安装环境：

ubuntu12.04, python 2.7.6

### 应用

bintrees提供了丰富的API,涵盖了通常的多种应用。下面逐条说明其应用。

• 引用

>>>import bintrees

Warning:FastBinaryTreenot available,usingPython version BinaryTree.Warning:FastAVLTreenot available,usingPython version AVLTree.Warning:FastRBTreenot available,usingPython version RBTree.

>>>from bintrees importBinaryTree#只引入了BinartTree>>>from bintrees import*#三个模块都引入了
• 实例化

>>> btree =BinaryTree()>>> btreeBinaryTree({})>>> type(btree)<class'bintrees.bintree.BinaryTree'>
• 逐个增加键值对：.setitem(k,v) .复杂度O(log(n))(后续说明中，都会有复杂度标示，为了简单，直接标明：O(log(n)).)

>>> btree.__setitem__("Tom","headmaster")>>> btreeBinaryTree({'Tom':'headmaster'})>>> btree.__setitem__("blog","http://blog.csdn.net/qiwsir")>>> btreeBinaryTree({'Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})
• 批量添加：.update(E) E是dict/iterable，将E批量更新入btree. O(E*log(n))

>>> adict =[(2,"phone"),(5,"tea"),(9,"scree"),(7,"computer")]>>> btree.update(adict)>>> btreeBinaryTree({2:'phone',5:'tea',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})
• 查找某个key是否存在：.contains(k) 如果含有键k，则返回True,否则返回False. O(log(n))

>>> btreeBinaryTree({2:'phone',5:'tea',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})>>> btree.__contains__(5)True>>> btree.__contains__("blog")True>>> btree.__contains__("qiwsir")False>>> btree.__contains__(1)False
• 根据key删除某个key-value：.delitem(key), O(log(n))

>>> btreeBinaryTree({2:'phone',5:'tea',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})>>> btree.__delitem__(5)#删除key=5的key-value,即：5:'tea' 被删除.>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})
• 根据key值得到该kye的value：.getitem(key)

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})>>> btree.__getitem__("blog")'http://blog.csdn.net/qiwsir'>>> btree.__getitem__(7)'computer'>>> btree._getitem__(5)#在btree中没有key=5，于是报错。Traceback(most recent call last):File"<stdin>", line 1,in<module>AttributeError:'BinaryTree'object has no attribute '_getitem__'
• 迭代器：.iter()

>>> btree        BinaryTree({2:'phone',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})>>> aiter = btree.__iter__()>>> aiter<generator object<genexpr> at 0xb7416dec>>>> aiter.next()#注意：next()一个之后，该值从list中删除2>>> aiter.next()7>>> list(aiter)[9,'Tom','blog']>>> list(aiter)#结果是空[]>>>bool(aiter)#but,is TrueTrue
• 数的数据长度：.len(),返回btree的长度。O(1)

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','Tom':'headmaster','blog':'http://blog.csdn.net/qiwsir'})>>> btree.__len__()5
• 找出key最大的k-v对：.max(),按照key排列，返回key最大的键值对。

• 找出key最小的键值对：.min()

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree'})>>> btree.__max__()(9,'scree')>>> btree.__min__()(2,'phone')
• 两棵树的关系运算

>>> other =[(3,'http://blog.csdn.net/qiwsir'),(7,'qiwsir')]>>> bother =BinaryTree()#再建一个树>>> bother.update(other)#加入数据>>> botherBinaryTree({3:'http://blog.csdn.net/qiwsir',7:'qiwsir'})>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree'})>>> btree.__and__(bother)#重叠部分部分BinaryTree({7:'computer'})>>> btree.__or__(bother)#全部BinaryTree({2:'phone',3:'http://blog.csdn.net/qiwsir',7:'computer',9:'scree'})>>> btree.__sub__(bother)#btree不与bother重叠的部分BinaryTree({2:'phone',9:'scree'})>>> btree.__xor__(bother)#两者非重叠部分BinaryTree({2:'phone',3:'http://blog.csdn.net/qiwsir',9:'scree'})
• 输出字符串模样，注意仅仅是输出的模样罢了：.repr()

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree'})>>> btree.__repr__()"BinaryTree({2: 'phone', 7: 'computer', 9: 'scree'})"
• 清空树中的所有数据:.clear(),O(log(n))

>>> bother   BinaryTree({3:'http://blog.csdn.net/qiwsir',7:'qiwsir'})>>> bother.clear()>>> botherBinaryTree({})>>>bool(bother)False
• 浅拷贝：.copy(),官方文档上说是浅拷贝，但是我做了操作实现，是下面所示，还不是很理解其“浅”的含义。O(n*log(n))

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree'})>>> ctree = btree.copy()>>> ctreeBinaryTree({2:'phone',7:'computer',9:'scree'})>>> btree.__setitem__("github","qiwsir")#增加btree的数据>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>> ctreeBinaryTree({2:'phone',7:'computer',9:'scree'})#这是不是在说明属于深拷贝呢？>>> ctree.__delitem__(7)#删除ctree的一个数据>>> ctreeBinaryTree({2:'phone',9:'scree'})>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})

>>> ctreeBinaryTree({2:'phone',9:'scree'})>>> ctree.discard(2)#删除后，不返回值，或者返回None>>> ctreeBinaryTree({9:'scree'})>>> ctree.discard(2)#如果删除的key不存在，也返回None>>> ctree.discard(3)>>> ctree.__delitem__(3)#但是，.__delitem__(key)则不同，如果key不存在，会报错。Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/usr/local/lib/python2.7/site-packages/bintrees/abctree.py", line 264,in __delitem__self.remove(key)File"/usr/local/lib/python2.7/site-packages/bintrees/bintree.py", line 124,in removeraiseKeyError(str(key))KeyError:'3'
• 根据key查找，并返回或返回备用值：.get(key[,d])。如果key在树中存在，则返回value,否则如果有d，则返回d值。O(log(n))

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>> btree.get(2,"algorithm")'phone'>>> btree.get("python","algorithm")#没有key='python'的值，返回'algorithm''algorithm'>>> btree.get("python")#如果不指定第二个参数，若查不到，则返回None>>>
• 判断树是否为空：is_empty().根据树数据的长度，如果数据长度为0,则为空。O(1)

>>> ctreeBinaryTree({9:'scree'})>>> ctree.clear()#清空数据>>> ctreeBinaryTree({})>>> ctree.is_empty()True>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>> btree.is_empty()False
• 根据key、value循环从树中取值：

.items([reverse])—按照(key,value)结构取值;
.keys([reverse])—key
.values([reverse])—value. O(n)
.iter_items(s,e[,reverse]—s,e是key的范围，也就是生成在某个范围内的key的迭代器 O(n)

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>>for(k,v)in btree.items():...print k,v...2 phone7 computer9 screegithub qiwsir>>>for k in btree.keys():...print k...279github>>>for v in btree.values():...print v...phonecomputerscreeqiwsir>>>for(k,v)in btree.items(reverse=True):#反序...print k,v...github qiwsir9 scree7 computer2 phone>>> btreeBinaryTree({2:'phone',5:None,7:'computer',8:'eight',9:'scree','github':'qiwsir'})>>>for(k,v)in btree.iter_items(6,9):#要求迭代6<=key<9的键值对数据...print k,v...7 computer8 eight>>>
• 删除数据并返回该值：

.pop(key[,d]), 根据key删除树的数据，并返回该value，但是如果没有，并也指定了备选返回的d，则返回d，如果没有d，则报错；
.pop_item(),在树中随机选择(key,value)删除，并返回。

>>> ctree = btree.copy()>>> ctreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>> ctree.pop(2)#删除key=2的数据，返回其value'phone'>>> ctree.pop(2)#删除一个不存在的key，报错Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/usr/local/lib/python2.7/site-packages/bintrees/abctree.py", line 350,in pop    value =self.get_value(key)File"/usr/local/lib/python2.7/site-packages/bintrees/abctree.py", line 557,in get_valueraiseKeyError(str(key))KeyError:'2'>>> ctree.pop_item()#随机返回一个(key,value),并已删除之(7,'computer')>>> ctreeBinaryTree({9:'scree','github':'qiwsir'})>>> ctree.pop(7,"sing")#如果没有，可以返回指定值'sing'
• 查找数据,并返回value：.set_default(key[,d])，在树的数据中查找key,如果存在，则返回该value。如果不存在，当指定了d,则将该（key,d）添加到树内；当不指定d的时候，添加(key,None). O(log(n))

>>> btreeBinaryTree({2:'phone',7:'computer',9:'scree','github':'qiwsir'})>>> btree.set_default(7)#存在则返回'computer'>>> btree.set_default(8,"eight")#不存在，则返回后备指定值，并加入到树'eight'>>> btreeBinaryTree({2:'phone',7:'computer',8:'eight',9:'scree','github':'qiwsir'})>>> btree.set_default(5)#如果不指定值，则会加入None>>> btreeBinaryTree({2:'phone',5:None,7:'computer',8:'eight',9:'scree','github':'qiwsir'})>>> btree.get(2)#注意，.get(key)与.set_default(key[,d])的区别'phone'>>> btree.get(3,"mobile")#不存在的 key,返回但不增加到树'mobile'>>> btreeBinaryTree({2:'phone',7:'computer',8:'eight',9:'scree','github':'qiwsir'})
• 根据key删除值

.remove(key),删除(key,value)
.remove_items(keys),keys是一个key组成的list,逐个删除树中的对应数据

>>> ctreeBinaryTree({2:'phone',5:None,7:'computer',8:'eight',9:'scree','github':'qiwsir'})>>> ctree.remove_items([5,6])#key=6，不存在，报错Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/usr/local/lib/python2.7/site-packages/bintrees/abctree.py", line 271,in remove_itemsself.remove(key)File"/usr/local/lib/python2.7/site-packages/bintrees/bintree.py", line 124,in removeraiseKeyError(str(key))KeyError:'6'>>> ctreeBinaryTree({2:'phone',7:'computer',8:'eight',9:'scree','github':'qiwsir'})>>> ctree.remove_items([2,7,'github'])#按照 列表中顺序逐个删除>>> ctreeBinaryTree({8:'eight',9:'scree'})