Algorithm 为什么插入排序的最佳情况是O(n)&;不是O(n^2)?

Algorithm 为什么插入排序的最佳情况是O(n)&;不是O(n^2)?,algorithm,sorting,Algorithm,Sorting,我很难理解为什么o(n)中插入排序的最佳情况 for(int i=0;i0;j--){ int k=j-1; if(a[j]11,因此无需再查看落在11之前的元素。 第3步:以元素15为例,查找落在它之前的元素(即元素13),如15>13,因此无需再查看落在13之前的元素。 步骤4:以元素17为例,查找落在它前面的元素(即元素15),如17>15,因此无需再查看落在15之前的元素。 第5步:以元素19为例,查找落在它之前的元素(即元素17),如19>17,因此无需再查看落在17之前的元素 正如我

我很难理解为什么o(n)中插入排序的最佳情况

for(int i=0;i0;j--){
int k=j-1;
if(a[j]

让我们考虑一个示例初始数组[1,2,3,4,5]大小=5。 第一个循环将从i=0变为大小-1 第二个循环将从i变为1,但让我们假设,内部for循环也从0变为大小-1,换句话说,内部for循环也会执行(n-1)次,类似于外部for循环 我同意不会有交换,但会有比较&它将完全等同于未排序的数组? 然后n-1(外环)*n-1(内环)=n^2-n+1=O(n^2)


有人能解释一下我错在哪里吗?

这里有一种实现插入排序的方法

获取一个输入列表和一个初始为空的输出列表

迭代输入列表,并将每个项目放在输出列表上的适当位置。从第一个元素开始,遍历输出列表,找到适当的位置

现在,如果输入已排序,则插入点将始终位于输出列表的开头或结尾。第一种可能性对应于最佳情况情景;第二种情况对应于最坏情况

例如,我的输入数据是:4 3 2 1

然后,输出列表构建为:

4
3 4
2 3 4
1 2 3 4

由于查看第一个元素只需要O(1),因此时间复杂度取决于输入的大小,即O(N)。

您的代码始终以O(N^2)运行。在找到元素应该位于的位置时,必须中断内部for循环。

插入排序的最佳情况是当数组已经排序时O(n)

但是,对于排序的情况,您的算法仍然需要O(n^2)。所以,只有当条件失败时,才应该进入第二个循环。这样,在排序列表的情况下,您将永远不会进入内部循环

查看以下链接:


首先,这似乎不是用于插入排序的正确代码。您似乎正在以相反的方式使用冒泡排序代码。
在插入排序代码中,您不会将一个小元素替换为它前面的每个大元素,而是浏览它前面的所有大元素,仅当我们处于没有元素留下或没有更多大元素的位置时,然后我们将小元素放置在该位置,并移动所有其他后续元素

作为O(n)时间的一部分:
让我们考虑五个已经排序的元素的数组——ARR[11,13,15,17,19]。我们从第一个位置元素移动到最后一个位置。
第1步:接受元素11,因为它是第一个元素,所以我们保持原样。
第2步:以元素13为例,查找落在它之前的元素(即元素11),如13>11,因此无需再查看落在11之前的元素。
第3步:以元素15为例,查找落在它之前的元素(即元素13),如15>13,因此无需再查看落在13之前的元素。
步骤4:以元素17为例,查找落在它前面的元素(即元素15),如17>15,因此无需再查看落在15之前的元素。
第5步:以元素19为例,查找落在它之前的元素(即元素17),如19>17,因此无需再查看落在17之前的元素

正如我们所看到的,对于五个已经排序的元素,我们只需要5个比较,因此对于'n'排序的元素,我们只需要O(n)个比较。


我希望上面的例子能澄清你的疑问

将方法更改为具有此中断条件,您将获得最佳案例复杂性O(n)

void insertionSort0(列表)
{
int循环=0;
对于(int i=1;i=0;j--)
{
loop++;
if((整数)list.get(j)>target)
{
set(j+1,(整数)list.get(j));
pos=j;
}
其他的
{
打破
}
}
列表。设置(位置、目标);
}
System.out.println(“插入排序的循环输入”+循环);
}

考虑以下插入排序的实现:

    for (i=1; i<n; i++) {
        j=i;
        while ((j>0) && (s[j] < s[j-1])) {
            swap(&s[j],&s[j-1]);
            j = j-1;
        }
    }
(i=1;i0)和(s[j]{ 掉期(s[j]、&s[j-1]); j=j-1; } }
任何排序算法的最佳情况是输入已经按排序顺序进行。在这种情况下,while循环中的条件总是返回false,因此它只对外部for循环进行迭代,以O(n)时间复杂度在线性时间内完成任务

在计算最佳情况复杂度方面没有任何有用的应用。话虽如此,当数组已经排序时,您的算法会浪费时间。每次
a[i+1]>=a[i]
@n.m.时,您都可以跳过内部循环,您说最好的情况没有应用程序,可能最好的情况或接近最好的情况在随机数据中并不经常出现,但随后您继续推荐仅对此类数据有意义的代码更改。在某些情况下,人们希望数据的顺序接近排序,在这种情况下,运行时将更接近O(N)而不是O(N^2)。感谢guyz,我现在理解了我犯错误的地方。他使用的是数组,而不是列表。这里的区别非常无关紧要,@Gumbo.Insertion sort的最佳情况是当值已经按升序排列时。您所描述的是最糟糕的情况,即对于每个插入的值,必须移动所有以前插入的值,这将导致ψ(n^2)。我在这里描述的是插入排序
    void insertionSort0(List<Integer> list)
{
    int loop=0;
    for(int i=1;i<list.size();i++)
    {
        int target=(Integer)list.get(i);
        int pos=0;

        for(int j=i-1;j>=0;j--)
        {
            loop++;
            if((Integer)list.get(j)>target)
            {
                list.set(j+1, (Integer)list.get(j));
                pos=j;
            }
            else
            {
                break;
            }


        }


            list.set(pos, target);

    }
    System.out.println("loop in for insertion sort" +loop);
}
    for (i=1; i<n; i++) {
        j=i;
        while ((j>0) && (s[j] < s[j-1])) {
            swap(&s[j],&s[j-1]);
            j = j-1;
        }
    }