Java 时间复杂度修正的bubblesort

Java 时间复杂度修正的bubblesort,java,algorithm,sorting,complexity-theory,Java,Algorithm,Sorting,Complexity Theory,为bubblesort编写以下java代码: public void sort() { for(int i = 1; i < getElementCount() ; ++i) { for(int j = getElementCount()-1; j >= i; j--) { if (cmp(j,j-1) < 0) swap(j, j-1); } } } 我现在编写了Bubblesort的改进版本,其中排序

为bubblesort编写以下java代码:

public void sort() {
    for(int i = 1; i < getElementCount() ; ++i) {
        for(int j = getElementCount()-1; j >= i; j--) {
            if (cmp(j,j-1) < 0) swap(j, j-1);
        }
    }
}
我现在编写了Bubblesort的改进版本,其中排序方法“sort()”如下所示:

public void sort() {
    boolean done = false;
    for(int i = 1; i < getElementCount() && !done; ++i) {
        done = true;
        for(int j = getElementCount()-1; j >= i; j--) {
            if (cmp(j,j-1) < 0) {
                swap(j, j-1);
                done = false;
            }
        }
    }
}
public void sort(){
布尔完成=假;
对于(int i=1;i=i;j--){
if(cmp(j,j-1)<0){
互换(j,j-1);
完成=错误;
}
}
}
}

有人能解释一下如何计算后一种算法的时间复杂度吗?我认为它是在一次比较n个元素,因此它在最好的情况下具有复杂性O(1),在最坏的情况下具有复杂性O(n^2),但我不知道我是否正确,我想知道如何思考这个问题

复杂性告诉程序员处理数据需要多长时间

O(1)复杂性表示,无论有多少个元素,它只需要一次操作

在数组中插入一个值将具有O(1)

例如

在最好的情况下,您必须循环整个数组并比较每个元素。 您的复杂度代码是O(n),其中n是数组中的元素数。
在最坏的情况下,您必须为每个元素运行一次数组,这将导致复杂性为O(n*n)

我刚刚查看了您所做的工作,它与您之前列出的完全相同。您已经设置了一个布尔条件done=false,然后您正在检查它的求反,它将始终计算为true-与之前的逻辑完全相同。您可以删除代码中的done,您将看到它的运行完全相同。就像前面一样,您将有一个最佳情况复杂性O(n)和一个最坏情况复杂性O(n^2)。任何排序算法都不可能是O(1),因为至少您必须在列表中移动一次,这会给出O(n)

最坏情况:如果数组按排序相反的顺序(降序)排序,它将显示最坏的时间复杂度O(N^2)

最佳情况:如果数组按排序顺序排列,则内部循环将至少遍历每个元素一次,因此它是O(N)->(如果使用代码中不存在的done中的信息中断循环)

在任何情况下都不能是O(1)(事实上,在数学上不可能得到比O(N)更低的函数,因为对于基于比较的排序,排序的下界是ω(N)


ω(N)是最低可能的函数,为了进行比较,您必须至少查看一次所有元素。

最好的方法是使用西格玛符号表示循环,如下所示(一般情况):

这里的“c”是指在最内层循环内执行的
if
cmp
swap
的恒定时间

对于最佳情况(修改的气泡排序),运行时间应如下所示:


如果在最佳情况下对N个元素进行一次比较,时间复杂度将为O(N),因为比较的数量取决于元素的数量。关于它的最坏情况,正如你所说的是O(N^2)。这和“常规”的气泡排序有什么不同?!?嗨,乔瓦尼。如果数组按递增顺序排序,并且我使用冒泡排序(如上所述),那么它仍然必须遍历每个元素,以检查它们是否都已排序。同时,在改进的版本中,它只在数组中运行一次,而且由于它已排序,因此它在那里完成,而不必像未改进的冒泡排序那样在整个数组中运行。我希望这是有意义的。如果你有一个循环在另一个循环中,两个循环同时查看所有元素,那么最好和最坏的情况都是O(n^2)你的意思是O(n^2)吗?谢谢你的回答,但我想知道:如果两种算法的最好和最坏情况相同,那么改进的bubblesort为什么会更有效?(因为互联网上说泡泡糖运动最好和最坏的情况是O(n)和O(n^2))不完全一样。O(1)表示在最坏情况下,所需的步数不取决于值n。实际的数量可能非常大(这就是为什么对于小数据集,复杂度较高的算法比复杂度较小的算法更有效——它们的常数小得多,从而抵消了复杂度的差异)。不同之处在于,由于“!done”,它甚至没有进入第一个for循环。是的,如果我删除布尔值,它是完全相同的,但是对于布尔值,它被标记为“完成排序”的速度比第一个算法快,因为第一个算法必须在标记为完成之前比较每个元素。我知道你想说什么,但它是多余的。在冒泡排序的每个第n次迭代中,第n个最小(或最大,取决于排序方式)元素都会“冒泡”到第n个顶部位置(因此而得名)。您试图检查的条件已经被算法的性质所满足。此外,您还在内部循环的末尾设置done=false,因此当外部循环开始执行时done仍然为false(就像第一次一样)如果我有一个完全排序的数组,然后同时运行这两个算法,改进的bubblesort算法会被标记为“完成”,比常规的bubblesort快得多。我真的不明白为什么在这种情况下条件是多余的,请解释原因是因为您在内部循环中重置done=false。现在,当外部循环再次启动时,done=false->与第一次启动循环时完全相同,并且一直持续到结束。您可以通过在两个方法中放置断点并查看循环执行的次数来尝试这一点。你会发现它们完全一样。还要注意,在考虑我们假设的复杂性时,n上升到无穷大->一个或两个步骤的约化
public void sort() {
    boolean done = false;
    for(int i = 1; i < getElementCount() && !done; ++i) {
        done = true;
        for(int j = getElementCount()-1; j >= i; j--) {
            if (cmp(j,j-1) < 0) {
                swap(j, j-1);
                done = false;
            }
        }
    }
}
array[100] = value;