简介: 冒泡排序(Bubble Sort)是最为直观和易懂的排序算法之一,它的思想是前后比较,若前者大于后者就把前者和后者交换位置,就像一个重量大的泡泡一样,慢慢地浮至其他轻的泡泡之下。
Java代码:
//冒泡排序,普通版本,平均时间复杂度n^2,在数组排完前面几轮已经有序后仍会继续
//排序,故在数组有序时时间复杂度仍为n^2
public static void bubbleSort1(int[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n - i - 1; j++) {
if (a[j] < a[j - 1]) {
swap(a, j, j-1);
}
}
}
}
public static void swap(int[] a, int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
冒泡排序的平均时间复杂度为n^2,当数组在前面几轮排序后已经有序的情况下仍会继续执行剩余的比较,所以当数组基本有序时,其排序的时间复杂度也为n^2,但是这种情况有一个优化的方法可以将其优化为n,那就是加入一个flag标识,当某一轮循环没有元素的交换时说明已经有序,直接结束冒泡排序即可:
```java
//冒泡排序,加入flag标识,当任何一轮没有交换元素时将其置为false,说明已经有序
//平均时间复杂度为n^2,最好为n,只进行前面的几轮排序
public static void bubbleSort(int[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
boolean flag = true;
for (int j = i + 1; j < n - i; j++) {
if (a[j] < a[j - 1]) {
flag = false;
swap(a, j, j-1);
}
}
if (flag) {
return;
}
}
}
public static void swap(int[] a, int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
```
动画演示:
https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html
思考:
1、第一轮for循环的作用是标识这是第几个要进行冒泡排序的数,如i=0时,表示这是对数组的第一个数进行冒泡排序,假如数组有5个数,就要进行4次冒泡排序,因为最后一个数无需排序,它一定是最小的了。
2、第二轮for循环的作用是定义比较的次数是多少次,如一个数组有5个数,那么在对以一个数进行冒泡排序时,需要比较(5-1)= 4次,第二个数进行比较时,需要比较3次。
3、若前者小于后者,并不是结束循环,而是用后者去和接下来的数比较。如数组3 2 4 1,3比较到4的时候,判断3小于4,所以不能进到if中,即把索引往下移给4,用4和接下来的数进行比较,这样的作用是一轮下来,一定能筛选出大数将其排序到后面。
4、冒泡排序是有缺点的:假如数组有n个元素,那么第一轮需要进行n-1次比较,第二轮需要n-2次比较,所以n-1轮后共比较
(n-1)+(n-2)+...+1 ~= n^2/2次,即算法的时间复杂度0与n^2成正比,所以大O表示法表示为O(n^2),是时间复杂度很大的一种排序算法。