冒泡排序算法
依次比较相邻的两个数,将小数放在前面,大数放在后面,直到将最大数放在最后,然后进行第二趟比较
第一趟排序:
- 将序列中的第一个元素与第二个元素比较
- 如果第一个元素 > 大于第二个元素,则交换
- 然后比较第二个元素与第三个元素,以此类推
- 直到第 N-1 个与第 N 个元素比较完为止,然后进行第二趟排序
第二趟排序:
- 重复上述操作,以此类推
- 直到第 N-2个元素与第 N-1个元素比较完为止,然后进行第三趟排序
......
以上我们可以看出,每次需要比较的元素都在不断减少,因为我们每一趟排序都会把最大的元素交换到后面合适的位置,所以后面已经交换好的元素不用再参与下次循环了
也就是下面代码第二层 for 循环中的(数组长度 - i - 1)
- 减 i 的作用就是上面我们说的比较好的元素不再进行下次比较,所以下次比较的元素不断减少。
- 因为我们每次比较的都是当前元素和后一个元素,所以只需要遍历到倒数第二个元素即可,因此进行减 1 操作。
若共有 N 个元素,则需进行 N 趟比较
然后第一趟中再需要 N-1 次比较,第二趟需要 N-2次比较......
时间复杂度
最好情况:O(n²),因为即使是个有序数组,也需要都检查一遍
平均情况:O(n²)
最坏情况:O(n²),是一个倒序的数组,每个都需要进行交换
改进后代码的时间复杂度
(下面会提到改进后的代码)
最好情况:O(n),是一个正序的数组
平均情况:O(n²)
最坏情况:O(n²),是一个倒序的数组,每个都需要进行交换
Python代码
"""冒泡排序"""
# 升序
ls = [5, 2, 0, 1, 3, 1, 4]
for i in range(len(ls)):
for j in range(len(ls) - i - 1):
if ls[j] > ls[j + 1]:
temp = ls[j]
ls[j] = ls[j + 1]
ls[j + 1] = temp
print(ls)
Java代码
package algorithm;
public class Sort {
// 冒泡排序算法,升序
public static void bubbleSort(int[] array) {
for (int i = 0 ; i < array.length ; i++) {
for (int j = 0 ; j < array.length - i - 1 ; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
public static void main(String[] args) {
int[] array = new int[]{5, 2, 0, 1, 3, 1, 4};
Sort.bubbleSort(array);
// 打印数组
for (int i = 0 ; i < array.length ; i++) {
System.out.print(array[i] + " ");
}
}
}
改进后的Java代码
通过以上代码我们发现,假如,待排序列已经是有序的,或者在排序的过程中,循环还没有结束就已经有序了,那么我们已经不需要再继续循环下去了,此时直接退出即可
因此,我们需要一个标志,来检测待排序列是否有序
public static void bubbleSort(int[] array) {
boolean flag;
for (int i = 0 ; i < array.length ; i++) {
flag = true;
for (int j = 0 ; j < array.length - i - 1 ; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = false;
}
}
// 如果flag为true,则说明没有进入第二层循环
// 也就是待排数组已经是有序的,所以直接退出即可
if (flag) {
break;
}
}
}
此时的时间复杂度最优情况已经可以达到 O(n) 了