python - 某些情况导致我的二分搜索进入无限循环

标签 python binary-search

当搜索不在列表中(但在列表范围内)的任何内容以及大于最大数字的任何内容时,我陷入了无限循环。例如,当在列表 [1,2,5,6] 中搜索 2 时,我的函数返回索引 1,这是正确的。如果我搜索 -1,它会返回 False,这是正确的。但是,如果我搜索 100 或 4,它就会陷入无限循环。

def binary_search(a_list, item):

    if not a_list:
        return False

    mid = len(a_list)//2

    print "Middle is: {}".format(a_list[mid])
    print a_list


    while len(a_list) > 0:
        if a_list[mid] == item:
            return mid
        elif a_list[mid] > item:
            return binary_search(a_list[:mid], item)
        elif a_list[mid] < item:
            return binary_search(a_list[mid:], item) + mid
        else:
            return False

a = binary_search([1, 2, 3, 4, 6, 7, 8], 5) # infinite loop
b = binary_search([1, 2, 3, 4, 6, 7, 8], 100) # infinite loop
c = binary_search([1, 2, 3, 4, 6, 7, 8], 8) # works correctly
d = binary_search([1, 2, 3, 4, 6, 7, 8], -2) # works correctly

最佳答案

这是我用来检查您的程序的代码。 pdb 允许您使用 s 一次执行一个命令,或使用 继续执行下一个 pdb.set_trace() c.你可以像这样使用它:

import pdb

def binary_search(a_list, item):

    if not a_list:
        return False

    mid = len(a_list)//2

    print "Middle is: {}".format(a_list[mid])
    print a_list


    print a_list, item
    pdb.set_trace()

    while len(a_list) > 0:
        if a_list[mid] == item:
            return mid
        elif a_list[mid] > item:
            return binary_search(a_list[:mid], item)
        elif a_list[mid] < item:
            return binary_search(a_list[mid:], item) + mid
        else:
            return False

现在,您的程序存在许多问题,最明显的是循环和递归的组合。这很少是正确的。我还要指出, while 循环中的每种情况都有一个 return 语句,因此 while 循环仅具有导致列表大小为 的搜索的效果>0 不返回任何内容。我怀疑这就是你想要的。

第二个问题是您尝试返回 midFalse 的索引。你想做的事情没有问题。问题在于将 binary_search(...) 添加到 mid 中。这样做不好的原因是,在 Python 中,当您像数字一样使用 False 时,它的计算结果为 0。尝试在解释器中运行这些:

False * 5 # => 0
False + 5 # => 5
False == 0 # => True
False is 0 # => False

这意味着,如果您的代码以其他方式工作并且搜索不成功,您仍然会在很多时候返回一个整数答案。在添加 mid 时,False 值将会丢失。为了避免这种情况,我下面给出的代码不使用递归,因此 return False 是最终的。它直接转到首先调用 binary_search 的人,而不是任何之前的递归调用。您仍然可以编写递归解决方案,但几乎肯定需要进行类似 if binary_search(...) is False: 的比较,然后 在代码中的某个位置需要担心 is== 之间的差异然后您可能会想更频繁地使用 is,这是一个坏主意。

我还认为 a_list[mid:] 也存在一些问题。我没有确认这一点,但我认为您希望 a_list[mid+1:] 排除您已确认不是您要查找的元素的中间元素。不管怎样,我的替代代码根本不使用切片,所以我不会担心它。

这是我相信可以满足您要求的代码。

def binary_search(a_list, item):

    if not a_list:
        return False

    mid = len(a_list)//2
    start = 0 # new and important
    end = len(a_list) # new and important

    while start < end: # new and important
        if a_list[mid] > item:
            end = mid
            mid = (end - start) // 2 # new and important
        elif a_list[mid] < item:
            start = mid + 1
            mid = start + (end - start) // 2 # new and important
        else:
            return mid

    return False

请注意递归调用的删除以及 startend 的添加。它们跟踪您正在搜索列表的哪一部分,而不是您之前使用的列表切片。

关于python - 某些情况导致我的二分搜索进入无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39933884/

相关文章:

python - Base64 转换小数

python - 仅从 BeautifulSoup 获取数字而不是整个 div

python - 子任务会继承父任务的队列吗?

python - PyPi 下载计数似乎不切实际

Python webdriver : driver. get(URL) 无法在单元测试中打开 - 通过控制台工作

arrays - 如何使用元素值除以数组总和的概率返回元素的索引

java - 使用后缀数组搜索后缀

java - 二分查找 - 错误

C 二分查找

java - Java 中的二进制搜索,Mastermind Game