简单选择排序和冒泡排序区别
我一直搞不太清这两个具体区别。打算研究下。
我认为两种主要区别是(有不同意见请告知):冒泡每次循环都是相邻两数的比较(内层循环都是j和j+1比较),选择排序是某一下标元素与其他下标元素依次比较(内层循环是i和j的比较)。
一、冒泡排序
依次对相邻两数作比较,若前面的大于后面的,则交换。
第一次循环后,最大的数已经出现在最后的。
第二次循环后,第二大的数在倒数第二的位置上。
依此循环,知道数组有序。排序过程如下:
public static void sort(int[] a){
int len = a.length;
for(int i = 0; i< len; i++){ //控制循环的次数。
for(int j = 0; j<len-i-1;j++){ //控制比较数的下标。
if(a[j]>a[j+1]){
swap(a, j, j+1);
}
System.out.print("i = " +i+", j = "+j+" ");
print(a);
}
}
}
private static void swap(int[]a, int i, int j ){
int temp = a[i];
a[i] = a[j];
a[j]= temp;
}
优化1:控制外层循环的次数
对上述冒泡方法可以进行优化,就是定义个标记,来辅助控制外层循环的次数。
/**
* 使用标志位来控制外层循环的次数
* @param a
*/
public static void sort1(int[] a){
int len = a.length;
boolean flag = true; //控制外层循环次数,若数组已经有序了,就不比较了。
for(int i = 0; i< len; i++){
flag = true;
for(int j = 0; j<len-i-1;j++){
if(a[j]>a[j+1]){
flag = false;
swap(a, j, j+1);
}
}
if(flag){
break;
}
}
}
优化2:在上面进一步,控制内外层循环的次数。
/**
* 记录上次交换的位置,以此为内层循环的界限。
* @param a
*/
public static void sort2(int[] a){
int len = a.length;
boolean flag = true; //控制外层循环次数,若数组已经有序了,就不比较了。
int lasttemp = len-1;
for(int i = 0; i< len; i++){
flag = true;
int last = lasttemp;
for(int j = 0; j<last;j++){
if(a[j]>a[j+1]){
flag = false;
swap(a, j, j+1);
lasttemp =j; //记录最后以此交换的位置。此位置之后为有序的。
}
}
if(flag){
break;
}
}
}
二、简单选择排序:
从第一个元素开始,与后续元素进行比较,若前面大于后面的,则交换;依此循环。
public static void selectSort(int[]a){
int len = a.length;
for(int i = 0; i<len;i++){
for(int j = i+1;j<len;j++){
if(a[i]>a[j]){
swap(a, i, j);
}
System.out.print("i = " +i+", j = "+j+" ");
print(a);
}
}
}
选择排序优化思路和冒泡不一样。冒泡能如此优化是因为每轮循环后,都能知道数组的局部排序情况,而选择不行。
选择排序可以减少交换次数,每轮循环结束后再进行交换。网上很多,这里不说了。若有更好的优化方法,请告知。