二分查找与 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的替代,用来更快的查找一个元素的位置

 

posted @ 2018-08-29 09:09  梁颖666  阅读(485)  评论(0编辑  收藏  举报