双层for循环,外层负责要总体循环的次数(n-1),内层外循环负责一次外层for循环里面的两两数字比较的次数,通过内层for循环,每完成一次外层for循环,就会确定一个最大(最小)的数
简单实现
public static int[] bubbSort(int[] a){
int length=a.length;//防止for循环中重复计算长度
for(int i=0;i<length-1;i++){
for(int j=0;j<length-1-i;j++){//若外层for循环i!=0,说明最右面至少有一个数是确定的,这个数不需要比较
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
return a;
}
优化一(外层for循环)
如图,第四次和第五次已经有序,但是仍需要遍历,浪费资源,设置一个flag(因为flag的目的是简化外层for循环,所以flag需定义成全局变量),在for循环的时候,判断上一次内层循环是否执行if语句,若执行说明数组尚未明确为有序数组,若未执行if语句则说明此时数组已经有序
public static int[] bubbSort(int[] a){
int length=a.length;
boolean flag=true;
for(int i=0;i<length-1;i++){
for(int j=0;j<length-1-i;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
flag=false;
}
}
if(flag){
return a;
}
flag=true;
}
return a;
}
优化二(内层for循环)
若内层for循环遍历的数组部分有序,若出现后面的几位数都已经有序,但是内层for循环还会去两两比较,其主要问题出在内层for循环中的j<length-1-i,若定义一个变量每次内层for循环的时候,给这个变量赋值(值为if语句中的最后发生变化的j),这样j以后的数就不会两两比较
public static int[] bubbSort(int[] a){
int length=a.length;
boolean flag=true;
int last=length-1;//用于记录最后的标志位,初始值为后一位(i=0时,才能正常调用)
for(int i=0;i<length-1;i++){
int now=0;
for(int j=0;j<last;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
flag=false;
now=j;
}
}
last=now;
if(flag){
return a;
}
flag=true;
}
return a;
}
优化三
针对整个数组前面的几位数都有序,但是后面的几位数没有序的情况,如:2,3,4,5,6,0,1
如果只是一次内层for循环的话,若出现以上情况,需要遍历好几次外层for循环和内层for循环,而这样只需要遍历一次外层for循环
public static int[] bubbSort(int[] a){
int length=a.length;
boolean flag=true;
int last=length-1;
int count=0;//记录前面数字中已经有序的个数
for(int i=0;i<length-1;i++){
int now=0;
for(int j=0;j<last;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
flag=false;
now=j;
}
}
last=now;
if(flag){
return a;
}
flag=true;
for(int j=last;j>count;j--){//此时数组的在最前面和最后面的数已经确定,都为最小和最大的数(第一次除外)
if(a[j]<a[j-1]){
int temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
flag=false;
}
}
count++;
if(flag){
return a;
}
flag=true;
}
return a;
}