# 排序 - 冒泡排序(Bubble Sort)
# 冒泡排序介绍
它是一种较简单的排序算法。它会遍历若干次要排序的数列,每次遍历时,它都会从前往后依次的比较相邻两个数的大小;如果前者比后者大,则交换它们的位置。这样,一次遍历之后,最大的元素就在数列的末尾! 采用相同的方法再次遍历时,第二大的元素就被排列在最大元素之前。重复此操作,直到整个数列都有序为止!
我们先分析第 1 趟排序
- 当 i=5,j=0 时,a [0]<a [1]。此时,不做任何处理!
- 当 i=5,j=1 时,a [1]>a [2]。此时,交换 a [1] 和 a [2] 的值;交换之后,a [1]=30,a [2]=40。
- 当 i=5,j=2 时,a [2]>a [3]。此时,交换 a [2] 和 a [3] 的值;交换之后,a [2]=10,a [3]=40。
- 当 i=5,j=3 时,a [3]<a [4]。此时,不做任何处理!
- 当 i=5,j=4 时,a [4]>a [5]。此时,交换 a [4] 和 a [5] 的值;交换之后,a [4]=50,a [3]=60。
于是,第 1 趟排序完之后,数列 {20,40,30,10,60,50} 变成了 {20,30,10,40,50,60}。此时,数列末尾的值最大。
根据这种方法:
- 第 2 趟排序完之后,数列中 a [5…6] 是有序的。
- 第 3 趟排序完之后,数列中 a [4…6] 是有序的。
- 第 4 趟排序完之后,数列中 a [3…6] 是有序的。
- 第 5 趟排序完之后,数列中 a [1…6] 是有序的。整个数列也就是有序的了。
# 复杂度和稳定性
# 冒泡排序时间复杂度
冒泡排序的时间复杂度是 O (N2)。 假设被排序的数列中有 N 个数。遍历一趟的时间复杂度是 O (N),需要遍历多少次呢?N-1 次!因此,冒泡排序的时间复杂度是 O (N2)。
# 冒泡排序稳定性
冒泡排序是稳定的算法,它满足稳定算法的定义。 算法稳定性 – 假设在数列中存在 a [i]=a [j],若在排序之前,a [i] 在 a [j] 前面;并且排序之后,a [i] 仍然在 a [j] 前面。则这个排序算法是稳定的!
冒泡排序如何减少时间复杂度:
如果某次内部循环完全不交换,这意味着数组已经有序,我们可以在这个点上停止冒泡排序。
/** | |
* 冒泡排序最终版,减少时间复杂度 | |
* @author wspstart | |
* @create 2023-01-23 21:04 | |
*/ | |
public class BubbleSort { | |
public static void sort(int[] a){ | |
for (int i = a.length - 1; i > 0; i--) { | |
boolean swapped = false; | |
for (int j = 0; j < i; j++) { | |
if (greater(a[j],a[j + 1])){ | |
exch(a,j,j+1); | |
swapped = true; | |
} | |
} | |
if (!swapped){ | |
break; | |
} | |
println(i,a); | |
} | |
} | |
/** | |
* 比较 v 元素是否大于 w 元素 | |
* | |
* @param v | |
* @param w | |
* @return | |
*/ | |
private static boolean greater( int v, int w) { | |
return v > w; | |
} | |
/** | |
* 数组元素 i 和 j 交换 | |
* | |
* @param a | |
* @param i | |
* @param j | |
*/ | |
private static void exch(int[] a, int i, int j) { | |
int temp; | |
temp = a[i]; | |
a[i] = a[j]; | |
a[j] = temp; | |
} | |
private static void println(int num, int[] a) { | |
System.out.println("第" + num + "次循环" + Arrays.toString(a)); | |
} | |
} |
测试代码:
/** | |
* @author wspstart | |
* @create 2023-01-23 21:13 | |
*/ | |
public class SortTest { | |
private int [] arr; | |
@BeforeEach | |
public void init(){ | |
// 给数组赋值 | |
arr = new int[]{20,40,30,10,60,50}; | |
} | |
@Test | |
void testBubbleSort(){ | |
BubbleSort.sort(arr); | |
} | |
} |