冒泡排序算法分析

1. 基本思想

冒泡排序的基本思想:
  对于待排序数列, 依次比较相邻元素, 若顺序相反, 则交换位置, 重复此步骤直至完成排序.

2. 过程演示

[5, 4, 3, 2, 1] 来演示整个排序过程

原始序列:    5, 4, 3, 2, 1

第一趟排序:  4, 5, 3, 2, 1
            4, 3, 5, 2, 1
            4, 3, 2, 5, 1
            4, 3, 2, 1, 5

第二趟排序:  3, 4, 2, 1,   5
            3, 2, 4, 1,   5
            3, 2, 1, 4,   5

第三趟排序:  2, 3, 1,   4, 5
            2, 1, 3,   4, 5

第四趟排序:  1, 2,   3, 4, 5

可以看出:
  每一趟排序都将所经过的最大的元素放在了最后的位置, 所以第 n趟排序并不需要关心倒数第 n + 1个元素.

3. 代码实现

// 冒泡排序
private static int[] bubbleSort(int[] arr) {
    for (int i = 0; i < arr.length; i++) {        
        boolean swapped = false;    // 第 (i + 1)次是否发生了元素交换
        for (int j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr, j , j + 1);
                printArr(j, j + 1, arr);    // 打印比较过程
                swapped = true;
            }
        }
        if (!swapped)    // 未发生元素交换的话, 表示数组已经是有序的了
            break;
    }
    return arr;
}
/* 
output: 
    原始数组: [5, 4, 3, 2, 1]
    i = 0, j = 1  ---> [4, 5, 3, 2, 1]
    i = 1, j = 2  ---> [4, 3, 5, 2, 1]
    i = 2, j = 3  ---> [4, 3, 2, 5, 1]
    i = 3, j = 4  ---> [4, 3, 2, 1, 5]
    i = 0, j = 1  ---> [3, 4, 2, 1, 5]
    i = 1, j = 2  ---> [3, 2, 4, 1, 5]
    i = 2, j = 3  ---> [3, 2, 1, 4, 5]
    i = 0, j = 1  ---> [2, 3, 1, 4, 5]
    i = 1, j = 2  ---> [2, 1, 3, 4, 5]
    i = 0, j = 1  ---> [1, 2, 3, 4, 5]
    排序后: [1, 2, 3, 4, 5]
*/

// 交换数组中指定索引处的元素位置
private static void swap(int[] arr, int i, int j) {
    if (i > arr.length - 1 || i < 0 || j > arr.length - 1 || j < 0) {
        throw new RuntimeException("索引值有误");
    }
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

// 打印数组元素
private static void printArr(int[] arr) {
    System.out.println(Arrays.toString(arr));
}

// 打印 i, j的索引, 和当前数组的顺序
private static void printArr(int i, int j, int[] arr) {
    System.out.print("i = " + i + ", j = " + j + "  ---> ");
    printArr(arr);
}

4. 复杂度分析

假设: 给定一个含有 n个元素的序列

最好情形:
  给定序列是正序, 那么走一趟即可完成排序, 所需比较次数C和记录移动次数M均达到最小值, 即:

Cmin = n - 1
Mmin = 0

所以, 冒泡排序最好的时间复杂度是 O(n)

最坏情形:
  给定序列是倒序, 那么需要进行 n - 1 趟排序, 第 i趟排序需要进行 n - i 次比较, 且每次比较都必须移动记录三次来达到交换位置的效果, 在这种情况下, 比较和移动次数均达到最大值.

所以, 冒泡排序最坏的时间复杂度是 O(n^2)

Cmax = n * (n - 1) / 2 = O(n^2)
Mmax = 3 * n * (n - 1) / 2 = O(n^2)

综上所述, 冒泡排序的平均时间复杂度是 O(n^2)

5. 总结

原文地址:https://www.cnblogs.com/bobo132/p/13950350.html