【问题标题】:How to implement a binary search?如何实现二分查找?
【发布时间】:2017-01-27 06:23:46
【问题描述】:

我正在尝试创建一个二进制搜索函数,我已经尝试使用下面的代码,但我是 python 的初学者;我在行 i == alist[i] 上收到错误“列表索引必须是整数,而不是 str”。你能帮我解决这个问题吗?这是整个代码:

def bsort(alist, i):
    left = 0
    right = len(alist)-1
    i == alist[i]

    [mid] = (left + right)//2

    if alist[mid] < i :
        left = [mid] + 1

    elif alis[mid] > i :
        right = [mid] + 1

    elif alist[mid] == i :
        print ("word found at", i )

    elif left > right:
        print ("Not Found!")       


i = input("Enter a search >")
alist = ["rat","cat","bat","sat","spat"]
bsort(alist, i)

【问题讨论】:

  • 地址是什么意思?
  • 输入是什么? i 是一个索引,它必须是一个整数。另请注意,二分搜索对无序序列没有太大帮助。
  • 请问我怎样才能让它工作?
  • 这取决于...您的用例是什么?您是想在列表中快速查找还是只是想对列表进行排序?如果您的目标是前者,那么您应该使用list.sort() 对列表进行排序,然后然后 对其执行二进制搜索。如果是后者,那么您需要花一些时间处理您的代码。
  • mid,而不是[mid]

标签: python algorithm python-3.x sorting binary-search


【解决方案1】:

您得到“列表索引必须是整数,而不是 str”,因为您将字符串作为列表中二进制搜索的输入,并在第 4 行将其用作列表的索引,这导致列表出现错误通过整数索引。

另一个问题: 1.你的列表必须在应用二分搜索之前进行排序, 2.第 6 行导致另一个错误,因为 int 对象不可迭代。 3.为了在列表中进行完整的搜索,你必须包含一个while循环,这将感知你的前两个if条件并帮助循环遍历列表。

此代码可能对您有所帮助:

def bsort(alist,blist,i):

left = 0
right = len(alist)-1

mid = (left + right)//2

while left <= right:    #  loop through the list
    if alist[mid] < i :
        left = mid + 1
    elif alist[mid] > i :
        right = mid + 1
    elif alist[mid] == i :
        print ("word found at", blist.index(i) )    # will print the original index of element i.e. before sorting
        exit()     #to stop through infinite looping
    elif left > right:
        print ("Not Found!")       

i = input("输入搜索 >") #你要搜索的字符串 alist = ["老鼠","猫","蝙蝠","sat","spat"] blist = alist[:] # 创建另一个列表以了解原始列表中的元素索引 alist.sort() # 排序列表执行二分查找 bsort(alist,blist,i)

【讨论】:

  • 使用blist.index() 导致python 使用线性搜索再次搜索数组...有效地消除了bsearch 的全部目的。为什么不直接打印出mid 的值?
  • 但简单地打印出 m 给出了元素 i 的新位置...因此这取决于问题是仅仅找出元素是否在列表中还是打印原始列表中的元素。如果问题属于第 1 类,那么甚至不需要打印 m,'yes' 或 'no' 就可以了。
  • 感谢您的帮助,我的问题是“类别 1”,以查找项目是否在列表中。
【解决方案2】:

因此,从您的问题的声音来看,您正试图让二进制 search 为您的示例工作。首先,知道二分查找仅在排序数据上可靠工作是很有用的。这与标准线性搜索完全不同,标准线性搜索总是会找到值,而不管顺序如何。您可能已经知道二分搜索是首选,因为它在每次迭代中消除了一半的潜在候选者,而线性搜索只消除了一个元素。话虽如此,让我们讨论一下我对您的程序所做的修改。首先,一些外观上的改变可以大大增加程序的清晰度。

1.) 使用描述性变量名称非常重要,它可以作为其他人阅读您的代码的注释,说明变量的内容和功能可能是什么。这在像 python 这样的语言中尤其重要,在这种语言中,仅通过阅读代码就不容易推断出变量类型。因此,我没有多次重用变量i,而是重命名了您的函数参数target,因为这是我们试图定位的搜索词,即我们的“目标”。我还将您的函数从 'bsort' 重命名,这意味着该函数对某些内容进行排序,改名为 'bsearch' 这是一个更合适的名称,因为它更准确地描述了函数的作用。

2.) 可以使用循环或递归来实现二进制搜索。为简单起见,我选择了使用循环的迭代路线。正如我之前提到的,二分搜索通过在每次迭代中消除一半的潜在搜索候选来工作。如果没有循环,您确实会淘汰一半的候选人(仅一次),但除非您非常幸运,否则您可能找不到您要搜索的术语!相反,您需要继续此过程,直到找到要搜索的术语。这是while True: 循环的功能。

3.) 最后,我们确保使用整数来访问列表的索引。 python 中的所有列表都从0 to n-1 索引,其中n 是列表中的元素数。我们无法使用诸如 2.5 之类的浮点值访问列表,因为这不对应于列表中的任何特定“槽”。同样,我们不能使用字符串来访问我们的元素,因为列表再次需要一个整数来执行查找。这就是mid = int((left + right)/2)的目的。

话虽如此,这应该可以满足您的预期目的。我希望这可以帮助你!我还鼓励您查看一些有关如何实现二分搜索的示例,例如 this one

def bsearch(alist, target):
    left = 0
    right = len(alist)-1

    while True:
        mid = int((left + right)/2)
        if alist[mid] < target :
            left = mid + 1
        elif alist[mid] > target :
            right = mid + 1
        elif alist[mid] == target :
            print ("word '" + target + "' found at " + str(mid))
            break
        elif left > right:
            print ("Not Found!")
            break       


i = input("Enter a search >")
alist = ["rat","cat","bat","sat","spat"]
alist.sort()
bsearch(alist, i)

【讨论】:

  • 我知道它需要是一个排序列表,我试图为列表中的每个变量分配一个数字。因此,如果列表是 0、1、2、3、4,如果“目标”小于 2,它将在 2 处拆分,那么它将再次减半。说 0 是它会划分的目标,直到它得到对应于单词的 0。但是 .sort 也可以。感谢您的帮助
  • 所以这正是这里发生的事情!从算法的角度来看,您的解决方案很接近,您真的只需要添加循环。如果列表是[0,1,2,3,4],而我们的目标是0,那么“已检查”项将为210,此时我们的目标已找到。
【解决方案3】:

首先是==,它检查是否相等并且不赋值。使用单个 = 而不是 == 进行分配。

此外,您的方法将 i 作为字符串,然后使用字符串来引用列表的索引。这会产生错误。

您正在使用二进制搜索的整数方法来查找不正确的字符串。特别是因为您的字符串既不按长度排序,也不按字母顺序排序。请参考其他一些方法来执行此操作。

Binary string search in Python 3.x

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 2018-04-13
    • 1970-01-01
    • 2023-03-05
    • 2014-05-10
    • 2016-02-23
    • 1970-01-01
    • 2019-12-25
    相关资源
    最近更新 更多