以下python代码似乎正常工作。如果我根据注释更改代码,它似乎仍然有效。如果我使用high = middle
而不是high = middle - 1
而不是low = middle
而不是low = middle + 1
时,算法是否会失败?
haystack = [3,5,7,8,9,23,65,89,100]
needle = 89
low = 0
high = len(haystack)
while (low < high):
middle = (high + low)//2
if (needle < haystack[middle] ):
high = middle - 1 # what about just high = middle?
elif (needle > haystack[middle]):
low = middle + 1 # what about just low = middle?
elif (needle == haystack[middle]):
print ("The needle was found at index " + str (middle))
break
答案 0 :(得分:2)
那是因为您仅考虑值在列表中的情况(也许在某些情况下列表包含元素并且需要这些行,但我想不到其中之一) 考虑以下简单情况:
haystack = [1,2]
needle = 3
the rest of the code...
如果没有当前版本的代码,您将陷入无限循环。
注意:如@ vivek_23所述,您已经在检查中间位置,因此不需要进行额外的迭代。
答案 1 :(得分:0)
为使循环完成,每次迭代必须将范围至少减小1。如果没有,则将得到无限循环。
如果您到达low
是偶数且high = low+1
的地步,则middle
的计算将始终返回low
。您将不断测试相同的位置。
答案 2 :(得分:0)
关于为什么要进入无限循环的解释与您的条件有关:
while (low < high):
不更新条件(低或高)将意味着您的循环条件不会改变,low
(如果开始低于高)将永远小于high
。
另一个注意事项是,它将有助于(您)将代码分解为功能。将来,它将使您的调试过程更加轻松。这是一个不太Python的实现:
def binary_search(sorted_list, target_value, low, high):
if (low > high):
return False
mid = (low + high) // 2
if (mid == 0 and sorted_list[mid] != target_value):
return False
if sorted_list[mid] == target_value:
return True
elif sorted_list[mid] < target_value:
return binary_search(sorted_list, target_value, mid + 1, high)
else:
return binary_search(sorted_list, target_value, low, mid)
如果要确保可以访问列表中的每个项目,请尝试测试算法是否找到列表中的所有内容:
sorted_list = [1, 2, 3, 4, 5, 6, 7, 8, 8, 9]
not_in_list = 42
def test_binary_search(sorted_list):
for each_item in sorted_list:
found = binary_search(sorted_list, each_item, 0, len(sorted_list) - 1)
if not found:
print("{} not found by binary_search".format(each_item))
else:
print("found {} ".format(each_item))
test_binary_search(sorted_list)
类似地,当给定不在列表中的项目时,您希望算法能够正确运行。
def test_item_not_found(sorted_list, item):
expected = False
actual = binary_search(sorted_list, item, 0, len(sorted_list) - 1)
status = "Passed" if actual == expected else "Failed"
print("status {} expected: {}, actual: {}".format(status, expected, actual))
test_item_not_found(sorted_list, not_in_list)