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

问题

思路说明

二叉树查找算法,在开发实践中,会经常用到。按照惯例,对于这么一个常用的东西,Python一定会提供轮子的。是的,python就是这样,一定会让开发者省心,降低开发者的工作压力。

python中的二叉树模块内容:

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

以上是用python写的,相面的模块是用c写的,并且可以做为Cython的包。

  • FastBinaryTree
  • FastAVLTree
  • FastRBTree

特别需要说明的是:树往往要比python内置的dict类慢一些,但是它中的所有数据都是按照某个关键词进行排序的,故在某些情况下是必须使用的。

安装和使用

安装方法

安装环境:

ubuntu12.04, python 2.7.6

安装方法

  • 下载源码,地址:https://bitbucket.org/mozman/bintrees/src
  • 进入源码目录,看到setup.py文件,在该目录内运行
python setup.py install

安装成功,ok!下面就看如何使用了。

应用

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

- 引用

如果按照一般模块的思路,输入下面的命令引入上述模块

>>> import bintrees

错了,这是错的,出现如下警告:(×××不可用,用×××)

Warning: FastBinaryTree not available, using Python version BinaryTree.

Warning: FastAVLTree not available, using Python version AVLTree.

Warning: FastRBTree not available, using Python version RBTree.

正确的引入方式是:

    >>> from bintrees import BinaryTree     #只引入了BinartTree
    >>> from bintrees import *              #三个模块都引入了

- 实例化

看例子:

    >>> btree = BinaryTree()
    >>> btree
    BinaryTree({})
    >>> type(btree)
    <class 'bintrees.bintree.BinaryTree'>

- 逐个增加键值对:.__setitem__(k,v) .复杂度O(log(n))(后续说明中,都会有复杂度标示,为了简单,直接标明:O(log(n)).)

看例子:

    >>> btree.__setitem__("Tom","headmaster")
    >>> btree
    BinaryTree({'Tom': 'headmaster'})
    >>> btree.__setitem__("blog","http://blog.csdn.net/qiwsir")
    >>> btree
    BinaryTree({'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)
    >>> btree
    BinaryTree({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))

看例子:

    >>> btree
    BinaryTree({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))

看例子:

    >>> btree
    BinaryTree({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' 被删除.
    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree', 'Tom': 'headmaster', 'blog': 'http://blog.csdn.net/qiwsir'})

- 根据key值得到该kye的value:.__getitem__(key)

看例子:

    >>> btree
    BinaryTree({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 True
    True

- 树的数据长度:.__len__(),返回btree的长度。O(1)

看例子:

    >>> btree
    BinaryTree({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__()

看例子:

    >>> btree
    BinaryTree({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)        #加入数据

    >>> bother
    BinaryTree({3: 'http://blog.csdn.net/qiwsir', 7: 'qiwsir'})
    >>> btree
    BinaryTree({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__()

看例子:

    >>> btree
    BinaryTree({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()
    >>> bother
    BinaryTree({})
    >>> bool(bother)
    False

- 浅拷贝:.copy(),官方文档上说是浅拷贝,但是我做了操作实现,是下面所示,还不是很理解其“浅”的含义。O(n*log(n))

看例子:

    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree'})
    >>> ctree = btree.copy()
    >>> ctree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree'})

    >>> btree.__setitem__("github","qiwsir")    #增加btree的数据
    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree', 'github': 'qiwsir'})
    >>> ctree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree'})     #这是不是在说明属于深拷贝呢?

    >>> ctree.__delitem__(7)    #删除ctree的一个数据
    >>> ctree
    BinaryTree({2: 'phone', 9: 'scree'})
    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree', 'github': 'qiwsir'})

- 移除树中的一个数据:.discard(key),这个功能与.__delitem__(key)类似.两者都不反悔值。O(log(n))

看例子:

    >>> ctree
    BinaryTree({2: 'phone', 9: 'scree'})
    >>> ctree.discard(2)    #删除后,不返回值,或者返回None
    >>> ctree
    BinaryTree({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 remove
      raise KeyError(str(key))
      KeyError: '3'

- 根据key查找,并返回或返回备用值:.get(key[,d])。如果key在树中存在,则返回value,否则如果有d,则返回d值。O(log(n))

看例子:

    >>> btree
    BinaryTree({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)

看例子:

    >>> ctree
    BinaryTree({9: 'scree'})
    >>> ctree.clear()   #清空数据
    >>> ctree
    BinaryTree({})
    >>> ctree.is_empty()
    True
    >>> btree
    BinaryTree({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)

看例子:

    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree', 'github': 'qiwsir'})
    >>> for (k,v) in btree.items():
    ...     print k,v
    ...
    2 phone
    7 computer
    9 scree
    github qiwsir
    >>> for k in btree.keys():
    ...     print k
    ...
    2
    7
    9
    github
    >>> for v in btree.values():
    ...     print v
    ...
    phone
    computer
    scree
    qiwsir
    >>> for (k,v) in btree.items(reverse=True):  #反序
    ...     print k,v
    ...
    github qiwsir
    9 scree
    7 computer
    2 phone

    >>> btree
    BinaryTree({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 computer
    8 eight
    >>>

- 删除数据并返回该值:

>>.pop(key[,d]), 根据key删除树的数据,并返回该value,但是如果没有,并也指定了备选返回的d,则返回d,如果没有d,则报错;

>>.pop_item(),在树中随机选择(key,value)删除,并返回。

看例子:

    >>> ctree = btree.copy()
    >>> ctree
    BinaryTree({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_value
        raise KeyError(str(key))
        KeyError: '2'

    >>> ctree.pop_item()   #随机返回一个(key,value),并已删除之
    (7, 'computer')
    >>> ctree
    BinaryTree({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))

看例子:

    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 9: 'scree', 'github': 'qiwsir'})
    >>> btree.set_default(7)    #存在则返回
    'computer'

    >>> btree.set_default(8,"eight")  #不存在,则返回后备指定值,并加入到树
    'eight'
    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 8: 'eight', 9: 'scree', 'github': 'qiwsir'})

    >>> btree.set_default(5)    #如果不指定值,则会加入None
    >>> btree
    BinaryTree({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'
    >>> btree
    BinaryTree({2: 'phone', 7: 'computer', 8: 'eight', 9: 'scree', 'github': 'qiwsir'})

- 根据key删除值

>>.remove(key),删除(key,value)

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

看例子:

    >>> ctree
    BinaryTree({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_items
        self.remove(key)
        File "/usr/local/lib/python2.7/site-packages/bintrees/bintree.py", line 124, in remove
        raise KeyError(str(key))
        KeyError: '6'

    >>> ctree
    BinaryTree({2: 'phone', 7: 'computer', 8: 'eight', 9: 'scree', 'github': 'qiwsir'})
    >>> ctree.remove_items([2,7,'github'])  #按照 列表中顺序逐个删除
    >>> ctree
    BinaryTree({8: 'eight', 9: 'scree'})

###以上只是入门的基本方法啦,还有更多内容,请移不到到文章开头的官方网站

Python中的二叉树查找算法模块,布布扣,bubuko.com

时间: 2024-10-25 21:03:28

Python中的二叉树查找算法模块的相关文章

Java中常用的查找算法——顺序查找和二分查找

Java中常用的查找算法——顺序查找和二分查找 一.顺序查找: a) 原理:顺序查找就是按顺序从头到尾依次往下查找,找到数据,则提前结束查找,找不到便一直查找下去,直到数据最后一位. b) 图例说明: 原始数据:int[] a={4,6,2,8,1,9,0,3}; 要查找数字:8 代码演示: import java.util.Scanner; /* * 顺序查找 */ public class SequelSearch { public static void main(String[] arg

Java中的二分法查找算法

[ 什么是二分查找 ]  二分查找又称为折半查找,该算法的思想是将数列按序排列,采用跳跃式方法进行查找,即先以有序数列的中点位置为比较对象, 如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分.以此类推不断缩小搜索范围. [ 二分查找的条件 ] 二分查找的先决条件是查找的数列必须是有序的. [ 二分查找的优缺点 ] 优点:比较次数少,查找速度快,平均性能好: 缺点:要求待查数列为有序,且插入删除困难: 适用场景:不经常变动而查找频繁的有序列表. [ 算法步骤描述 ] ①

【转】Python中操作mysql的pymysql模块详解

Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而后者不支持3.x版本. 本文测试python版本:2.7.11.mysql版本:5.6.24 一.安装 1 pip3 install pymysql 二.使用操作 1.执行SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Python中操作mysql的pymysql模块详解

Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,pymysql支持python3.x. 一.安装 pip install pymysql 二.使用操作 1.执行SQL #!/usr/bin/env pytho # -*- coding:utf-8 -*- importpymysql # 创建连接 conn =pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd

Python中的Apriori关联算法-市场购物篮分析

数据科学Apriori算法是一种数据挖掘技术,用于挖掘频繁项集和相关的关联规则.本模块重点介绍什么是关联规则挖掘和Apriori算法,以及Apriori算法的用法.此外,在小型企业场景中,我们将借助Python编程语言构建一个Apriori模型. 什么是关联规则挖掘? 如前所述,Apriori算法用于关联规则挖掘.现在,什么是关联规则挖掘?关联规则挖掘是一种用于识别一组项目之间的频繁模式和关联的技术. 例如,了解客户的购买习惯.通过查找顾客放置在其“购物篮”中的不同商品之间的关联和关联,可以得出

Python——递归、二分查找算法

递归函数 1. 递归 (1)什么是递归:在函数中调用自身函数(2)最大递归深度:默认997/998--是Python从内存角度出发做的限制 n = 0 def story(): global n n+= 1 print(n) story() #997/998 story() (3)修改最大深度:最好不要改--递归次数太多,则不适合用递归解决问题 import sys sys.setrecursionlimit(2000) #1997/1998 2. 递归的优点 会让代码变简单 3. 递归的缺点

python之路——二分查找算法

楔子 如果有这样一个列表,让你从这个列表中找到66的位置,你要怎么做? l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88] 你说,so easy! l.index(66)... 我们之所以用index方法可以找到,是因为python帮我们实现了查找方法.如果,index方法不给你用了...你还能找到这个66么? l = [2,3,5,10,15,16,18,22,26,30,32,35,41,

python中的正则表达式(re模块)

一.简介 正则表达式本身是一种小型的.高度专业化的编程语言,而在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. 二.正则表达式中常用的字符含义 1.普通字符和11个元字符: 普通字符 匹配自身 abc abc . 匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符 a.c abc \ 转义字符,使后一个字符改变原来的意思 a\.c;a\\c a.c;a\c * 匹配前一个字

深入JDK源码之Arrays类中的排序查找算法(转)

原文出处: 陶邦仁 binarySearch()方法 二分法查找算法,算法思想:当数据量很大适宜采用该方法.采用二分法查找时,数据需是排好序的. 基本思想:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功:若x小于当前位置值,则在数列的前半段中查找:若x大于当前位置值则在数列的后半段中继续查找,直到找到为止. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //针对int类型数组的二分法查找,key为要查找数的下