使用二进制搜索将元素插入到排序的数组中

时间:2014-01-21 00:21:46

标签: binary-search

我想在排序数组中插入一个元素(替换现有元素)

[1, 2, 3, 4, 5]

例如插入0并保持它应该替换的顺序1

[0, 2, 3, 4, 5]

并插入6并保持它应该替换5的顺序

[0, 2, 3, 4, 6]

我想使用二进制搜索,我创建了以下

int binary_search(int *a, int first, int last, int x) {

    int mid;

    while (first <= last) { /* was <, changed to <= */

        mid = (first + last) / 2;

        if (a[mid] == x)
            return mid;

        else if (a[mid] > x)
            last =  mid - 1;

        else
            first = mid + 1;
    }

    /* after the loop => first = last */

    if (a[first] > x)
        return first;
    else
        return first + 1;
}

我错过了什么,我如何证明我所做的事情会导致总是正确的结果?

3 个答案:

答案 0 :(得分:3)

我通常做的事情,我认为证明算法正确的最简单方法是将其视为最小单位。因此,首先给出一个算法可能会失败并测试它是否会失败的场景。

假设first = 0last = 1。然后,mid = (0 + 1 )/ 2 = 0。所以有3种可能的情况。

  • a[mid] == x,那么很棒,你就找到了答案。
  • a[mid] > x时,您将移动last = mid - 1 = -1。太棒了,你终止了因为last不大于first而且它是真的,因为x小于排序列表的第一个元素的值,所以{{1}是不可能的在列表中。
  • x时。那么你将移动你的a[mid] < x。现在,在这种情况下,您终止循环。但是,有一些问题,因为first = mid + 1 = 1可能具有您所寻找的价值。您只需跳过一个可能的选项。

以下是算法失败时的可视化情况。假设a[1]并表示x = 5F = first

      (1   5)   6   7   8   9   15
       ^   ^ 
       F   L

如您所见,粗体部分是可能的选项。在L = lasta[0]时,您有两个可能的选项a[1]first = 0。然后,当您计算last = 1时以及检测到mid = (0 + 1) / 2 = 0时。然后移动a[mid] = a[0] = 1 < 5first = 1。您终止循环,因为last = 1不再大于last,在这种情况下,您只需检查first,但跳过a[0]


所以这就是我的建议

a[1]

在您的代码中,您没有机制来判断您搜索的项目是否找不到。当找不到def binarysearch(a, x): low = 0 high = length(a) while low <= high: mid = (high + low) / 2 if (a[mid] == x): return mid elseif (a[mid] > x) : low = mid + 1 else : high = mid - 1 return -1 时,我返回-1。因此,您只需以这种方式创建函数x

replace

答案 1 :(得分:1)

请注意您的代码。如果你想用0,2,3,4,5中的6替换5。 第一次迭代:first = index 0,last = index 4,mid = index 2. 3&lt; 6所以现在首先是索引3,最后是4。下一次迭代:第一=索引3,最后=索引4,中=索引3. 4&lt;因此,现在首先是指数4. 4!&lt; 4,所以去,如果,否则。 a [4]是5,5&lt; 5。 6,所以返回第一个+ 1,这是索引5.该索引现在超出界限。

你需要确保你没有超出范围。如果你有数字1 2 4 5并且你想要插入3.你会做什么,覆盖2或4?都工作。您将通过您的代码自动替换4,但是您是否总是想要替换更高的数字,也许您想要做最接近的数字?这只是需要考虑的事情。

答案 2 :(得分:1)

我建议您对原始代码进行一些修改,然后您可以确保您的代码始终能够提供正确的结果:

  1. 在while循环中,你写了while(first&lt; = last):它应该被改为while(first&lt; last)和while循环之后,它会比较&#39; x&#39;用[first](或[last])。为了实现这一点,它们必须是相同的,即,循环必须在条件下中断&#34; first = last&#34;同样。
  2. 在while循环之后,我们需要添加一个检查,如果[first](或,a [last])等于x。如果是,则只返回该索引的值。
  3. 如果[第一]&gt; x,然后x可以插入位置&#39; first&#39;。
  4. 如果[第一]&lt; x,然后x将插入位置&#39; first + 1&#39;。
  5. 以下是我的代码版本:

    int binary_search(vector<int> a, int first, int last, int x) {
        int mid;
        while (first < last) {
            mid = (first + last) / 2;
            if (a[mid] == x)
                return mid;
            else if (a[mid] > x)
                last =  mid - 1;
            else
                first = mid + 1;
        }
        if (start == a.size())
            return a.size();
        else if(a[first] > x)
            return first;
        else
            return first+1;
    }
    

    编辑:假设我们希望在{1,3,5,6}中插入7。 为此,一旦我们走出循环,我们需要考虑“开始”的最终价值。变量。如果它等于数组的大小,那么新元素就会结束。我已相应更新了代码。