据我所知,while循环指定的二进制搜索应始终继续搜索,直到搜索空间的最小值和最大值相等为止。但是在测试它时,并且总是在已经对大多数项目进行排序后,它会陷入无限循环,因为mx
以某种方式获得了值-2
。
我想我可以改变while循环的条件来修补它,但我试图理解为什么它的行为原样,并试图用我的眼睛和纸张重复它但不能重现事件mx = -2
。
def insort(seq):
for a in xrange(1, len(seq)):
if seq[a] > seq[a - 1]:
continue
else:
mn, mx = 0, a - 1
while mn != mx:
pivot = mn + ((mx - mn) / 2)
if seq[a] > seq[pivot]:
mn = pivot + 1
else:
mx = pivot - 1
seq.insert(mn, seq.pop(a))
答案 0 :(得分:3)
注意:我使用的是python 2.7.3。我不确定其他版本的python是否会因分割而产生不同的结果,所以这里有一个抬头。
需要进行一些更改:
mn != mx
更改为mn < mx
pivot = mn + ((mx - mn) / 2)
语句更改为pivot = int(math.floor((mn + mx) / 2))
或pivot = mn + int(math.floor((mx - mn) / 2))
,以防止出现任何意外情况。mn
指示的搜索时间间隔,mx
更改为半开放时间间隔,由[mn, mx)
给出,因为这是我在手上时更熟悉的内容编码二进制搜索。因此,mx
最初应设置为a
,mx
应设置为pivot
而不是pivot - 1
seq[a] <= seq[pivot]
,如果if
测试是False
)。所以带编辑的代码应如下所示:
import math
def insort(seq):
for a in xrange(1, len(seq)):
if seq[a] > seq[a - 1]:
continue
else:
mn, mx = 0, a
while mn < mx:
pivot = mn + int(math.floor(((mx - mn) / 2)))
if seq[a] > seq[pivot]:
mn = pivot + 1
else:
mx = pivot
seq.insert(mn, seq.pop(a))
对于原始代码,我将举例说明mx
卡在-2
。
鉴于此列表:[10, 7, 8, 5, 13, 2, 6, 1, 50]
一切正常,直到索引为5的元素,其值为2
(通过添加一些print
语句自行验证)。由于seq[a] > seq[a-1]
为false(2
是迄今为止的最小元素),因此我们输入if语句的else分支。
此时:
seq = [5, 7, 8, 10, 13, 2, 6, 1, 50]
a = 5
mn = 0
mx = a - 1 = 4
从mn != mx
(0 != 4
)开始,我们进入while循环。 pivot
设置为0 + ((4 - 0) / 2)
= 2
。接下来我们执行if seq[a] > seq[pivot]
。 seq[a] = 2
,而seq[pivot]
= 8
和2 > 8
为False
,因此我们转到其他分支并执行mx = pivot - 1 = 2 - 1 = 1
此时:
seq = [5, 7, 8, 10, 13, 2, 6, 1, 50]
a = 5
mn = 0
mx = 1
我们再次在while循环中执行检查。 mn != mx
(0 != 1
),所以我们进入while循环的主体。我们设置pivot = 0 + ((1 - 0) / 2) = 0
(我使用python 2.7来执行此除法,因此请在repl处进行验证),然后执行检查seq[a] > seq[pivot]
(2 > 5
),即False
。因此,我们设置mx = pivot - 1 = 0 - 1 = -1
。
此时:
seq = [5, 7, 8, 10, 13, 2, 6, 1, 50]
a = 5
mn = 0
mx = -1
现在,我们在while循环mn != mx
(0 != -1
)执行检查,因此我们输入while循环的主体。 pivot = 0 + ((-1 - 0) / 2) = -1
。然后我们执行检查seq[a] > seq[pivot]
(seq[5] > seq[-1]
,将第5个元素与seq
的最后一个元素进行比较,换句话说2 > 50
),即{{1} }。所以False
。
现在我们已经到了最后一步:
mx = pivot - 1 = -1 - 1 = -2
在while循环检查seq = [5, 7, 8, 10, 13, 2, 6, 1, 50]
a = 5
mn = 0
mx = -2
,我们继续mn != mx
。请注意,这与上一步的枢轴相同。然后执行pivot = 0 + ((-2 - 0) / 2) = -1
(seq[5] > seq[-1]
),即2 > 50
。所以False
。我们最终处于与上述相同的状态。这就是你看到无限循环的原因。
最后,我只是想说,二进制搜索是一种非常棘手的编码算法,因为它很容易为边界索引犯错误。我已经手动编码了很多次,但我仍觉得它非常棘手。您可能也希望阅读此内容:http://en.wikipedia.org/wiki/Binary_search_algorithm
希望有所帮助!