当前位置:  开发笔记 > 编程语言 > 正文

Python中的二进制搜索(二分)

如何解决《Python中的二进制搜索(二分)》经验,为你挑选了7个好方法。

是否有一个库函数在列表/元组上执行二进制搜索并返回项目的位置(如果找到)和'False'(-1,None等),如果没有?

我在bisect模块中找到了函数bisect_left/right ,但即使该项不在列表中,它们仍会返回一个位置.这对于他们的预期用途来说非常好,但我只是想知道一个项目是否在列表中(不想插入任何内容).

我想过使用bisect_left然后检查那个位置的项目是否等于我正在搜索的项目,但这看起来很麻烦(我还需要检查边界是否可以大于我列表中的最大数字).如果有一个更好的方法我想知道它.

编辑为了澄清我需要这个:我知道字典非常适​​合这个,但我试图尽可能降低内存消耗.我的预期用法是一种双向查找表.我在表中有一个值列表,我需要能够根据它们的索引访问这些值.而且如果值不在列表中,我希望能够找到特定值的索引或None.

使用字典是最快的方法,但会(大约)加倍内存需求.

我在问这个问题,认为我可能忽略了Python库中的某些东西.正如Moe建议的那样,我似乎必须编写自己的代码.



1> Dave Abraham..:
from bisect import bisect_left

def binary_search(a, x, lo=0, hi=None):  # can't use a to specify default for hi
    hi = hi if hi is not None else len(a)  # hi defaults to len(a)   
    pos = bisect_left(a, x, lo, hi)  # find insertion position
    return (pos if pos != hi and a[pos] == x else -1)  # don't walk off the end


@volcano所以一般都是binsearch.
@TomSwirly并不像你的那么简单,但是正确而且仍然是一种改进:`如果hi是None:hi = len(a)`

2> Moe..:

为什么不查看bisect_left/right的代码并根据您的目的进行调整.

像这样:

def binary_search(a, x, lo=0, hi=None):
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        midval = a[mid]
        if midval < x:
            lo = mid+1
        elif midval > x: 
            hi = mid
        else:
            return mid
    return -1


我原本+ 1'这个,但现在我得出结论这不是一件好事.如果遵循这个答案,它将导致大量的代码重复,并且众所周知,对于二进制搜索来说真的很简单.
@Paweł:它们是两个等价的变体,取决于上限是包含还是排他.你可以将`hi = mid`改为`hi = mid-1`和`hi = len(a)`改为`hi = len(a)-1`和`while lo 为什么不做类似的事情:def binary_search(a,x,lo = 0,hi = None):i = bisect(a,x,lo,hi)返回i如果a [i] == x else -1抱歉格式化 - 不确定如何在注释arrea中正确执行此操作

3> Gregg Lind..:

这有点偏离主题(因为Moe的回答似乎完全符合OP的问题),但是从头到尾看整个过程的复杂性可能是值得的.如果您将事物存储在已排序的列表中(这是二进制搜索有帮助的地方),然后只检查是否存在,则会产生(最坏情况,除非指定):

排序列表

O(n log n)最初创建列表(如果它是未排序的数据.O(n),如果它已排序)

O(log n)查找(这是二进制搜索部分)

O(n)插入/删除(可能是O(1)或O(log n)平均情况,具体取决于您的模式)

而a set(),你正在招揽

O(n)创造

O(1)查找

O(1)插入/删除

在给定起始索引的情况下,排序列表真正得到的东西是"下一个","上一个"和"范围"(包括插入或删除范围),它们是O(1)或O(| range |).如果您不经常使用这些类型的操作,那么存储为集合以及排序显示可能会更好. set()在python中产生很少的额外开销.


排序列表还有另外一件事可以帮到你.O(n)有序遍历.如果设置为O(n log n),则最终必须将对数据的引用复制到列表中.

4> Petr Viktori..:

值得一提的是,bisect文档现在提供了搜索示例:http: //docs.python.org/library/bisect.html#searching-sorted-lists

(例如,提高ValueError而不是返回-1或None更像pythonic - list.index()就可以了.但是当然你可以根据需要调整这些例子.)



5> Imran..:

最简单的方法是使用bisect并检查一个位置以查看该项目是否存在:

def binary_search(a,x,lo=0,hi=-1):
    i = bisect(a,x,lo,hi)
    if i == 0:
        return -1
    elif a[i-1] == x:
        return i-1
    else:
        return -1


很好,但是如果你没有传递'hi'值代码barfs.我这样写:"def binary_search(a,x,lo = 0,hi = None):from bisect import bisect i = bisect(a,x,lo,hi或len(a))return(i- 1如果[i-1] == x else -1)"并且测试它如下:"for i in range(1,20):a = list(range(i))aa中的aa:j = binary_search (a,aa)如果j!= aa:print i,aa,j"

6> arainchi..:

这是正确的手册:

http://docs.python.org/2/library/bisect.html

8.5.1.搜索已排序列表

上面的bisect()函数对于查找插入点很有用,但是对于常见的搜索任务来说可能很棘手或难以使用.以下五个函数显示如何将它们转换为排序列表的标准查找:

def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    raise ValueError

所以稍微修改一下你的代码应该是:

def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    return -1



7> paulluap..:

我同意@ DaveAbrahams使用bisect模块的答案是正确的方法.他没有在答案中提到一个重要的细节.

来自文档 bisect.bisect_left(a, x, lo=0, hi=len(a))

二分模块不需要提前预先计算搜索数组.您只需出示端点来bisect.bisect_left代替它使用的默认值0len(a).

对我来说更重要的是,寻找值X使得给定函数的误差最小化.为此,我需要一种让bisect_left算法调用我的计算的方法.这很简单.

只需提供一个定义__getitem__为的对象a

例如,我们可以使用bisect算法找到任意精度的平方根!

import bisect

class sqrt_array(object):
    def __init__(self, digits):
        self.precision = float(10**(digits))
    def __getitem__(self, key):
        return (key/self.precision)**2.0

sa = sqrt_array(4)

# "search" in the range of 0 to 10 with a "precision" of 0.0001
index = bisect.bisect_left(sa, 7, 0, 10*10**4)
print 7**0.5
print index/(10**4.0)

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有