这就是我自己编写的内容,我理解了这里所做的一切:
import java.util.Arrays;
public class Decision{
public static void main (String[]args){
int[] myArray = {1,8,3,0,2};
for(int i=0; i<myArray.length-1; i++){
if(myArray[i]<myArray[i+1]){
}
else{
int temp=myArray[i];
myArray[i]=myArray[i+1];
myArray[i+1]=temp;
}
System.out.println(Arrays.toString(myArray));
}
}
}
Output: [1, 3, 0, 2, 8]
因此我们首先检查数组中的第一个值是否小于下一个值。如果是,那么不要做任何事情。如果没有,那么交换两者。
这种排序算法的问题在于它不会将第一个值与第三个值交换为第二个值,或者第二个值与第五个值交换等等。
如果我们在代码中添加第二个重复for循环的for循环,我意识到这种方法很有效:
for(int n=myArray.length; n>1; n=n-1){
...
}
我也意识到这种类型叫做冒泡排序,但请解释一下这个for循环的重要作用,我很伤心,我无法理解它的作用是什么? :/
答案 0 :(得分:2)
假设这个算法的最坏情况,一个数组以相反的顺序排序,看看一个循环会发生什么
4 3 2 1 0 original array
3 4 2 1 0 after one swap
3 2 4 1 0 after two swaps
3 2 1 4 0 after three swaps
3 2 1 0 4 after the complete loop
您看到现在只有最大的元素在正确的位置,其余的仍然是相反的顺序。在第二次传递后,第二大元素也将在正确的位置,依此类推。
请注意,第一个之后的传递不必遍历整个数组(但不会受到影响),因为越来越多的元素已经到达最终位置。
答案 1 :(得分:2)
老实说,我对你的问题有点困惑。通常我建议添加诊断打印输出,但您已经有了一个。正如您所看到的,只进行一次传递最多可以将项目与旁边的项目交换。您无法以这种方式对数组进行完全排序,因为一旦您在[i]
处理一个元素,您的算法当然无法将该元素移动到其他任何位置。因此,如果在一次通过之后它没有处于最终正确的位置,那么它永远不会到达那里。 特别是,每次传递时,给定元素只能移动到 left 最多1个位置。最糟糕的情况是输入按降序排序在进入之前订购。
当你添加一个外部循环进行多次传递时,它每次都会对数组进行一次排序,直到最后它被排序。通过myArray.length - 1
次传递可以保证即使是最坏情况的元素也有机会被移动&#34;通过整个数组到正确的位置,因为在最坏的情况下输入它可以保证你能够将一个元素 left 移动到整个数组中(在一个长度为的数组中) n 需要 n-1 移动才能将最后一个位置的元素放到第一个位置 - 如果没有点击,则将其绘制在纸上并计数。 / p>
我的意思是,您真正应该学习的工具集中缺少一项重要的技能,那就是您需要习惯于可视化代码的功能。有几种方法可以做到这一点:
你选择了#5和#6,你只需要学习如何解释这些信息。例如Here is a working version of your sort(忽略其他潜在的代码改进,我确定其他答案可以帮助您沿着这些方向),添加一个额外的打印以分隔输出中的传递:
public static void main (String[]args){
int[] myArray = {1,8,3,0,2};
for(int n=myArray.length; n>1; n=n-1){
System.out.println("Outer loop: " + n);
for(int i=0; i<myArray.length-1; i++){
if(myArray[i]<myArray[i+1]){
}
else{
int temp=myArray[i];
myArray[i]=myArray[i+1];
myArray[i+1]=temp;
}
System.out.println(Arrays.toString(myArray));
}
}
}
输出:
Outer loop: 5
[1, 8, 3, 0, 2]
[1, 3, 8, 0, 2]
[1, 3, 0, 8, 2]
[1, 3, 0, 2, 8]
Outer loop: 4
[1, 3, 0, 2, 8]
[1, 0, 3, 2, 8]
[1, 0, 2, 3, 8]
[1, 0, 2, 3, 8]
Outer loop: 3
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
Outer loop: 2
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
[0, 1, 2, 3, 8]
正如您所看到的,在第一次通过后,它没有完全排序。第二遍更近了一点。在这种情况下,第三遍完成了它。在这种情况下,0举起的东西是0:0必须向左移动3个位置,所以你必须完成至少3次传球。
为了获得更清晰的图片,请尝试使用[8, 3, 2, 1, 0]
的最差情况输入的ideone示例。
答案 2 :(得分:1)
而不是添加第二个循环,你也可以说
boolean change = true;
while (change) {
change = false;
...
if (a[i] > a[i + 1]) { // write it like this and you don't need an else
change = true;
// swap
}
...
}
两者都有效,因为对数组进行排序所需的最大传递次数为n - 1
。对于最坏的情况,一个数组按降序排序而不是上升,元素将像水泡一样漂移到水的顶端。在第一次迭代中,第一个元素将在最后一个位置结束,在第二个迭代中,最初的第二个元素(现在第一个)将向上移动到第二个最后位置,依此类推。所以你可以看到你只需要n-1次迭代,因为在第(n-1)次迭代中,最初的第二个最后一个元素(现在是第一个)将以第二个位置结束,而最初的最后一个元素(现在是第一个)是已正确排序。
您还可以注意到,在每次迭代时(至少),数组末尾的另一个元素最终位于正确的位置,因此您可以在每次迭代时减少内部循环的最大值。