冒泡排序的改良版
循环优化
外循环优化
冒泡排序其实无需写死排序arr.length-1趟,因为在对一些相对有序的数列进行冒泡排序时,可能循环排序一遍这个数列就变得有序了,如:{1,2,3,4,5,7,6,8,9},只需要7和6调换一次数列就有序了。只要一次冒泡的过程没发生交换行为其实我们就可以判定这个数列是有序的了。
伪代码
public static void sort(int[] arr){
for(int i = 0;i<arr.length-1;i++){
//外循环
//使用一个标记位flag标记,初始化0
int flag = 0;
for(int j =0 ; j<arr.length-1;j++){
if (arr[j]>arr[j+1]){
//交换代码
//发生交换flag变1
flag = 1;
}
}
//判断内循环是否发生了交换行为
if (flag == 0) return;
}
}
内循环优化
在观察冒泡排序时,可以发现每次内循环一整趟执行完后,数列中就会有一个较大的数就会沉到数列中他应该到达的位置,如:假设一个无序的数列中有A,B,C三个数,并且A,B,C是数列中最大的三个数,有A>B>C,并且这三个数现在并不在它们数列中应该在的位置(数列后三位)那么第一趟排序后,A肯定沉到最低下,其次是B,C。那么冒泡排序的最后一趟交换确定了数列中有序和无序的边界,所以我们内循环只需循环无序的那一边就可以了,无需整个数列进行循环。
伪代码
public static void sort(int[] arr){
//记录最后交换位置
int k = arr.length-1;
for(int i = 0;i<arr.length-1;i++){
//定义一个pos,来记录最新交换位置
int pos = 0;
//根据最后交换位置k来优化内循环
for(int j =0 ; j<k;j++){
if (arr[j]>arr[j+1]){
//交换代码
//交换完后记录一下位置
pos = j;
}
}
//将最后的交换位置给k
k = pos;
}
}
内外循环结合代码
public static void sort(int[] arr){
int pos=0,k=arr.length-1;
for(int i = 0;i<arr.length-1;i++){
int flag = 0;
for(int j =0 ; j<k;j++){
if (arr[j]>arr[j+1]){
int tem = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tem;
pos = j;
flag = 1;
}
}
if (flag == 0) return;
k = pos;
}
}