python中的二进制搜索算法

Abd*_*ola 13 python algorithm binary-search

我试图在python中实现二进制搜索,并编写如下.但是,只要needle_element大于数组中的最大元素,我就无法停止.

你能帮我吗?谢谢.

def binary_search(array, needle_element):
    mid = (len(array)) / 2
    if not len(array):
        raise "Error"
    if needle_element == array[mid]:
        return mid
    elif needle_element > array[mid]:
        return mid + binary_search(array[mid:],needle_element)
    elif needle_element < array[mid]:
        return binary_search(array[:mid],needle_element)
    else:
        raise "Error"
Run Code Online (Sandbox Code Playgroud)

Rik*_*ggi 17

如同Lasse V.Karlsen在对该问题的评论中提出的那样,与a lowerupper索引合作会好得多.

这将是代码:

def binary_search(array, target):
    lower = 0
    upper = len(array)
    while lower < upper:   # use < instead of <=
        x = lower + (upper - lower) // 2
        val = array[x]
        if target == val:
            return x
        elif target > val:
            if lower == x:   # these two are the actual lines
                break        # you're looking for
            lower = x
        elif target < val:
            upper = x
Run Code Online (Sandbox Code Playgroud)
  • lower < upper 一旦你达到较小的数字(从左侧)将停止
  • if lower == x: break 一旦达到更高的数字(从右侧),将停止

例:

>>> binary_search([1,5,8,10], 5)   # return 1
1
>>> binary_search([1,5,8,10], 0)   # return None
>>> binary_search([1,5,8,10], 15)  # return None
Run Code Online (Sandbox Code Playgroud)

  • 你可以做`x =(lower + upper)// 2` (5认同)
  • @user1342336 二分搜索仅适用于已按排序顺序的列表。 (3认同)
  • 这不起作用.试一下清单:[7,9,2,4,8,6,5,1,8,5,3]. (2认同)

小智 10

为什么不使用bisect模块?它应该完成你需要的工作 - 更少的代码供你维护和测试.


int*_*jay 8

在这种情况下needle_element > array[mid],您当前传递array[mid:]给递归调用.但是你知道它array[mid]太小了,所以你可以传递array[mid+1:](并相应地调整返回的索引).

如果针大于数组中的所有元素,以这种方式执行将最终为您提供一个空数组,并且将按预期引发错误.

注意:每次创建子数组都会导致大型数组的性能下降.最好传入数组的边界.


Eci*_*ana 7

每次调用它时,array [mid:]都会创建一个新的子副本= slow.你也使用递归,在Python中也是如此.

试试这个:

def binarysearch(sequence, value):
    lo, hi = 0, len(sequence) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if sequence[mid] < value:
            lo = mid + 1
        elif value < sequence[mid]:
            hi = mid - 1
        else:
            return mid
    return None
Run Code Online (Sandbox Code Playgroud)

  • @Shnatsel ad"足够大的输入数组" - 鉴于我们所说的"二进制"搜索和CPython默认递归限制设置为1000(可以通过[`sys.setrecursionlimit`]设置为更多(http:// docs. python.org/library/sys.html#sys.setrecursionlimit))我们正在讨论的大小最大为2**1000的数组,也称为~10 ^ 300 ... (7认同)
  • 不仅递归很慢 - 如果数组足够长,它实际上会在你的脸上爆炸,因为Python没有尾递归优化,并且在给定足够大的输入数组时将耗尽堆栈帧. (2认同)