插入排序算法使用二进制搜索错误

时间:2013-11-10 13:22:21

标签: c++ algorithm insertion-sort

我运行以下代码,即使用二进制搜索的插入排序算法,找到正在插入的项目的正确位置而不是线性搜索,但结果中有两个数字未正确排序!

#include <iostream>
using namespace std;

void insertion_sort (int a[], int n /* the size of array */)
{
    int i, temp,j;
    for (i = 1; i < n; i++)
    {
        /* Assume items before a[i] are sorted. */
        /* Pick an number */
        temp = a[i];

        /* Do binary search to find out the
           point where b is to be inserted. */

        int low = 0, high = i - 1, k;

        while (high-low>1)
        {
            int mid = (high + low) / 2;

            if (temp <= a[mid]) 
                high = mid;
            else 
                low = mid;
        }

        /* Shift items between high and i by 1 */
        for (k = i; k > high; k--)
            a[k] = a[k - 1];

        a[high] = temp;
    }
}


int main()
{
    int A[15]={9,5,98,2,5,4,66,12,8,54,0,11,99,55,13};
    insertion_sort(A,15);
    for (int i=0; i<15; i++)
        cout<<A[i]<<endl;
    system("pause");
    return 0;
}

输出:

enter image description here

为什么?

3 个答案:

答案 0 :(得分:1)

这里需要注意的一些事情:

  1. 二进制搜索不会给你任何东西,因为你需要移动所有元素来创建空间。所以它实际上增加算法的总成本(虽然不是渐近)。

  2. 由于这是C ++,因此无需在使用它的for循环之前的任何地方声明k(只需使用for(int k; ...))。

  3. 分析算法的开头:i = 0 - &gt; low = high = 0.所以你的while循环不会执行。然后,无论元素是否应该被移动,你的for(k)循环都会交换元素0和1.这是错误编号1.

  4. i的第二次迭代:while循环不会再次执行,因为low = 0且high = 1,并且无论你交换了什么,至少元素1和2.错误编号2。

  5. 现在请注意,无论如何,每次下一次迭代都会将最初位于索引0的元素(在测试代码中为= 9)进一步移动到最后一个索引。

  6. 所以你可能会在检查第二次迭代之后看到(i)循环假设a [i]之前的元素被排序是错误的,因此算法也是错误的。

答案 1 :(得分:1)

#include <iostream>
using namespace std;

void insertion_sort (int a[], int n /* the size of array */)
{
    int i, temp,j;
    for (i = 1; i < n; i++)
    {
        /* Assume items before a[i] are sorted. */
        /* Pick an number */
        temp = a[i];

        /* Do binary search to find out the
           point where b is to be inserted. */

高限应该高于范围而不包括搜索,因为你可能需要在最后插入,即什么都不做。

        // int low = 0, high = i - 1, k;
        int low = 0, high = i, k;

此处条件应为low < high,而不是low + 1 < high

        // while (high-low>1)
        while (low < high)
        {
            int mid = (high + low) / 2;

            if (temp <= a[mid]) 
                high = mid;
            else 

如果a[mid]严格大于temp,则要插入的最低位置为mid + 1

                // low = mid;
                low = mid + 1
        }

        /* Shift items between high and i by 1 */
        for (k = i; k > high; k--)
            a[k] = a[k - 1];

        a[high] = temp;
    }
}


int main()
{
    int A[15]={9,5,98,2,5,4,66,12,8,54,0,11,99,55,13};
    insertion_sort(A,15);
    for (int i=0; i<15; i++)
        cout<<A[i]<<endl;
    system("pause");
    return 0;
}

答案 2 :(得分:1)

最简单的可能修复:将lowhigh初始化为int low = -1, high = i;。您要做的是找到索引lowhigh,以便0low的所有元素都是&lt; a[i]以及highi-1的所有元素均为a[i]。您的初始化不起作用,因为它没有捕获所有元素a[0], ..., a[i-1]大于a[i]时的极端情况以及当所有这些元素都小于a[i]时的极端情况。