Python插入排序与二进制搜索不(但几乎)工作

时间:2013-08-04 21:13:02

标签: python

据我所知,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))

1 个答案:

答案 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最初应设置为amx应设置为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 != mx0 != 4)开始,我们进入while循环。 pivot设置为0 + ((4 - 0) / 2) = 2。接下来我们执行if seq[a] > seq[pivot]seq[a] = 2,而seq[pivot] = 82 > 8False,因此我们转到其他分支并执行mx = pivot - 1 = 2 - 1 = 1

此时:

seq = [5, 7, 8, 10, 13, 2, 6, 1, 50]
a = 5
mn = 0
mx = 1

我们再次在while循环中执行检查。 mn != mx0 != 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 != mx0 != -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) = -1seq[5] > seq[-1]),即2 > 50。所以False。我们最终处于与上述相同的状态。这就是你看到无限循环的原因。

最后,我只是想说,二进制搜索是一种非常棘手的编码算法,因为它很容易为边界索引犯错误。我已经手动编码了很多次,但我仍觉得它非常棘手。您可能也希望阅读此内容:http://en.wikipedia.org/wiki/Binary_search_algorithm

希望有所帮助!