在列表中搜索时的二分查找错误

0 投票
3 回答
54 浏览
提问于 2025-04-12 01:35
def quickSort(arr):
  if len(arr) <= 1:
    return arr
  pivot = arr[int(len(arr)/2)]
  left = [x for x in arr if x < pivot]
  middle = [x for x in arr if x == pivot]
  right = [x for x in arr if x > pivot]
  return quickSort(left) + middle + quickSort(right)

def binSearch(sorted_arr, target):
  cen = int(len(sorted_arr)/2)
  if sorted_arr[cen] == target:
    return cen
  elif sorted_arr[cen] < target:
    return binSearch(sorted_arr[0:cen], target)
  else: 
    return binSearch(sorted_arr[cen:len(sorted_arr)], target)

my_array = [11, 9, 12, 7, 3, 8, 10, 2, 5, 1, 4, 6]
result = binSearch(quickSort(my_array), 13)
if result == -1:
  print("Element not found")
else:
  print(f"Element found at index {result}")

这是我的代码,还有我遇到的错误...

line 12, in binSearch
  if sorted_arr[cen] == target:
IndexError: list index out of range

现在我知道这个错误是什么意思。只是我不明白为什么会出现这个错误。我试着自己想象了一下,结果一切都很好!

3 个回答

0

你的快速排序函数没问题,让我来修一下二分查找的部分,我的代码能返回正确的索引值:

def binSearch(sorted_arr, target, left=0):
  if len(sorted_arr) == 0:
    return -1
  cen = len(sorted_arr) // 2
  if sorted_arr[cen] == target:
    return left + cen
  elif sorted_arr[cen] < target:
    return binSearch(sorted_arr[cen+1:], target, left + cen + 1)
  else:
    return binSearch(sorted_arr[:cen], target, left)
0

你的递归二分查找的实现有问题。

这里有一个改进的版本:

def binSearch(_list, _item):
    def _binSearch(_list, lo, hi):
        nonlocal _item
        if hi >= lo:
            mid = (hi + lo) // 2
            if _list[mid] == _item:
                return mid
            elif _list[mid] > _item:
                return _binSearch(_list, lo, mid - 1)
            else:
                return _binSearch(_list, mid + 1, hi)
        return -1
    if _list and _item >= _list[0] and _item <= _list[-1]:
        return _binSearch(_list, 0, len(_list)-1)
    return -1

用这个版本时,你只需要传入一个(已经排好序的)列表和你要找的项目。

不过,递归的二分查找通常会比迭代的方法慢,比如:

def binSearch(slist, item):
    if slist and item >= slist[0] and item <= slist[-1]:
        lo = 0
        hi = len(slist) - 1
        while lo <= hi:
            m = (lo + hi) // 2
            mv = slist[m]
            if mv == item:
                return m
            if mv < item:
                lo = m + 1
            else:
                hi = m - 1
    return -1

如果你想要最佳的性能,我建议:

from bisect import bisect_left

def binSearch(slist, item):
    if slist and item >= slist[0] and item <= slist[-1]:
        i = bisect_left(slist, item)
        if i != len(slist) and slist[i] == item:
            return i
    return -1
0

简单来说,你的二分查找函数里没有设置一个结束的条件。它一直在把你的数组一分为二。你需要加一个结束的条件,来检查你的数组长度是否为0。

if len(sorted_arr) == 0:
    return -1

想了解更多关于二分查找的内容,可以查看这里

撰写回答