1.算法思想:
冒泡排序是每次将最大(正序)或最小(逆序)的元素像我们的泡泡一样“冒”到序列末尾,直到整体有序为止。我们先来看看如下的过程:
比如我将 3,2,5,1,4从小到大排序
第一趟排序:
3比2大所以2,3交换位置得到 2,3,5,1,4
然后轮到3,5比较,3比5小不做交换
然后轮到5,1比较,5比1大 1,5交换位置 得到2,3,1,5,4
然后轮到5,4比较,5比4大,交换位置 得到2,3,1,4,5
如上结果可以看到 最大的5已结被“冒泡”到最末尾,下一轮排序的时候我们只需要轮询到4的位置,按照上述步骤循环,最后即可得到排序好的序列。
普通冒泡排序代码如下:
public void bubbleSort(int[] arr){
for(int i=0;i<arr.length;i++){
for(int j = 0;j< arr.length-i && j+1 <arr.length;j++){
if(arr[j]>arr[j+1]){
int tem=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tem;
}
}
}
}
但是想过没有,如果我们要排序的序列基本有序,我们经过几轮排序之后整个序列就有序了,那么我们还要继续遍历比较是不是就浪费了?那么有什么办法能避免这样的无用功呢?答案就是如果发现在某一趟排序中没有位置交换的话,那么我们就可以判定我们的序列已经被排好序了,如下是经过优化后的冒泡排序算法,通过设置标志位flag来判断某趟排序是否发生位置交换,如果没有则跳出外层循环。考虑到我们要排序的可能不只是基本数据类型int,所以如下代码采用java的泛型实现。
2.代码清单:
package Sort;
import java.util.Arrays;
/**
* @author xuyp 优化的冒泡排序
*/
public class BubbleSort {
public static <T extends Comparable<T>> T[] sort(T[] t) {
for (int i = 0; i < t.length; i++) {
boolean flag = true;//当没有发生交换 flag 为 true
for (int j = 0; j < t.length - i && j + 1 < t.length; j++) {
if (t[j].compareTo(t[j + 1]) > 0) {
T tem = t[j];
t[j] = t[j + 1];
t[j + 1] = tem;
flag = false;//发生交换 设置为false
}
}
if(flag) break;//当没有发生交换,说明已经有序了 直接退出
}
return t;
}
public static void main(String[] args) {
Integer[] iarr = { 3, 2, 1, 5, 4 };
iarr = sort(iarr);
System.out.println(Arrays.toString(iarr));
String[] sarr = { "a", "d", "c", "b" };
sarr = sort(sarr);
System.out.println(Arrays.toString(sarr));
Student[] stus = { new Student("d", 17), new Student("b", 18),
new Student("a", 18), new Student("c", 20) };
stus=sort(stus);
System.out.println(Arrays.toString(stus));
}
}
Student:
package Sort;
public class Student implements Comparable<Student> {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {//先按名字name排,然后按年龄age排
int res = this.name.compareTo(o.name);
if (res == 0) {
return this.age - o.age;
}
return res;
}
public String toString() {
return name + ":" + age;
}
}