zoukankan      html  css  js  c++  java
  • 二分查找与 bisect 模块

    # 二分查找算法  
    原理:
    在haystack(必须有序)中查找needle的位置
    该位置满足的条件是:
    把needle插入到这个位置之后,haystack还能保持升序
    也就是在这个函数返回的位置前面的值,都小于或等于needle的值。

    你可以先用bisect(haystack,needle) 查找位置index,
    在用haystack.insert(index,needle)来插入新值。
    但也可以用insort来一步到位,并且速度更快

    import bisect
    import sys
    
    HAYSTACK = [1,4,5,6,8,12,15,20,21,23,23,26,29,30]
    NEEDLES = [0,1,2,5,8,10,22,23,29,30,31]
    
    ROW_FMT = '{0:2d} @ {1:2d}    {2}{0:<2d}'
    
    def demo(bisect_fn):
        for needle in reversed(NEEDLES):
            position = bisect_fn(HAYSTACK,needle) # 计算元素应该出现的位置
            # print(needle,position)
            offset = position * '  |' # 利用位置来算出需要几个分隔符号
            print(ROW_FMT.format(needle,position,offset)) # 打印元素和应该出现的位置
    
    if __name__ == '__main__':
        # print(sys.argv[-1])
        if sys.argv[-1] == 'left': # 根据命令上最后一个参数来选用bisect函数
            bisect_fn = bisect.bisect_left
        else:
            bisect_fn = bisect.bisect
    
        print('DEMO:',bisect_fn.__name__) # 打印选中的函数
        print('haystack ->',' '.join('%2d'% n for n in HAYSTACK))
        demo(bisect_fn)

    结果:

    DEMO: bisect_right
    haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
    31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
    30 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |30
    29 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |29
    23 @ 11      |  |  |  |  |  |  |  |  |  |  |23
    22 @  9      |  |  |  |  |  |  |  |  |22
    10 @  5      |  |  |  |  |10
     8 @  5      |  |  |  |  |8 
     5 @  3      |  |  |5 
     2 @  1      |2 
     1 @  1      |1 
     0 @  0    0 
    bisect :
    可选参数:
    lo默认值为0 hi默认值为序列长度,len()作用于该序列的返回值

    bisect 函数其实是bisect.bisect_right函数的别名,


    bisect.bisect_right() 与 bisect.bisect_left() 区别:
    插入位置是原序列中跟被插入元素相等的元素的位置的时候:
    bisect.bisect_left: 新元素会被放置于相等元素的前面
    bisect.bisect_right: 新元素会被放置于相等元素的后面

    这个细微的差别可能对于整数序列来说没什么区别,
    但是对于那些值相等,但是形式不同的数据类型来说,结果就不一样了
    例如 1 == 1.0 但是 1 和 1.0 其实是两个不同的元素
    # 借助bisect可以用来建立一个用数字作为索引的查询表格
    import bisect
    def grade(score,breakpoints=[60,70,80,90],grades='FDCBA'):
        i = bisect.bisect(breakpoints,score)
        return grades[i]
    
    print([grade(score) for score in [33,99,77,70,89,90,100]])

    # 可以在很长的有序序列中作为index的替代,用来更快的查找一个元素的位置
  • 相关阅读:
    144. Binary Tree Preorder Traversal
    excel 文本拼接
    excel中文转拼音(方便复制版本)
    odoo 日志文件太大处理,logfile自动轮替
    编码对象或者字串中包含Unicode字符怎样转换为中文
    odoo 返回成功提示信息
    odoo 对res_partner,res_users添加字段重启服务失败处理
    odoo 根据当前记录的值动态筛选many2many,many2one,one2many数据
    odoo 中%()d的使用
    nginx 监听非标准端口80,重定向端口丢失问题解决
  • 原文地址:https://www.cnblogs.com/LYliangying/p/9552232.html
Copyright © 2011-2022 走看看