冒泡排序与鸡尾酒排序

#算法 #java

总结
  • 冒泡排序两个优化:无交换提前退出 + 记录最后交换位置缩小范围
  • 鸡尾酒排序是双向冒泡,轮次减半,对两端有序中间乱的数据更好
  • 实际项目直接用 Arrays.sort(TimSort),这两个只在面试里考优化思路

冒泡排序通过相邻元素比较交换,把最大值逐步"冒"到末尾。鸡尾酒排序是它的双向版本,每轮同时把最大值推到右边、最小值推到左边,轮次减半。

实际项目里这两个都不用,但面试会考优化思路。

1. 冒泡排序

两个优化点:

public static void bubbleSort(int[] arr) {
    int len = arr.length;

    for (int i = 0; i < len - 1; i++) {
        boolean sorted = true;
        int sortedBoundary = len - 1 - i;

        for (int j = 0; j < sortedBoundary; j++) {
            if (arr[j] > arr[j + 1]) {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                sorted = false;
                sortedBoundary = j; // 缩小下一轮的范围
            }
        }

        if (sorted) break; // 提前退出
    }
}

复杂度:最好 O(n)(已有序),平均/最坏 O(n²),空间 O(1),稳定。

2. 鸡尾酒排序

public static void cocktailSort(int[] arr) {
    int len = arr.length;

    for (int i = 0; i < len / 2; i++) {
        boolean sorted = true;
        int right = len - 1 - i;

        // 从左往右,把最大值推到右边
        for (int j = i; j < right; j++) {
            if (arr[j] > arr[j + 1]) {
                int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp;
                sorted = false;
                right = j;
            }
        }
        if (sorted) break;

        sorted = true;

        // 从右往左,把最小值推到左边
        for (int j = right; j > i; j--) {
            if (arr[j] < arr[j - 1]) {
                int tmp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = tmp;
                sorted = false;
            }
        }
        if (sorted) break;
    }
}

[2,3,4,5,1,6,7,8,9] 这种两端有序、中间乱的数据效果更好。

3. 对比

冒泡排序 鸡尾酒排序
方向 单向 双向
轮次 n-1 约 n/2
适用 通用 两端有序的数据

实际大数据量用快速排序或归并排序,小数据量(< 50)用插入排序,Java 内置的 Arrays.sort 是 TimSort(归并 + 插入),直接用就行。