【问题标题】:Insertion Sort algorithm by using binary search error使用二分查找错误的插入排序算法
【发布时间】:2013-11-10 22:43:49
【问题描述】:

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

#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;
}

输出:

为什么?

【问题讨论】:

  • 哪两个没有排序?你能输出你的结果吗?
  • 这里使用二分搜索的究竟有什么好处?您仍然会移动所有元素以腾出空间(除非比较非常昂贵)。

标签: c++ algorithm insertion-sort


【解决方案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 &lt; high,而不是low + 1 &lt; 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. 二分搜索不会给您任何东西,因为无论如何您都需要移动所有元素以腾出空间。所以它实际上增加了算法的总成本(虽然不是渐近的)。

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

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

    4. i 的第二次迭代:while 循环不会再次执行,因为低 = 0 和高 = 1,并且无论您如何交换至少元素 1 和 2。错误编号 2。

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

    因此,在检查 for(i) 循环的前两次迭代之后,您可能会发现 a[i] 之前的元素已排序的假设是错误的,因此算法也是错误的。

    【讨论】:

      【解决方案3】:

      最简单的解决方法:将lowhigh 初始化为int low = -1, high = i;。您想要做的是找到索引lowhigh,使得从0low 的所有元素都a[i],并且从highi-1 的所有元素都≥a[i]。您的初始化不起作用,因为它没有捕获所有元素 a[0], ..., a[i-1] 大于 a[i] 的极端情况以及所有这些元素都小于 a[i] 的极端情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-04
        • 1970-01-01
        • 2012-08-31
        • 1970-01-01
        • 1970-01-01
        • 2017-07-10
        相关资源
        最近更新 更多