排序算法之冒泡排序分析

冒泡排序

冒泡排序是重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(你所定义的逻辑顺序)错误就把他们交换过来。

走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

1)冒泡排序只会操作相邻的两个数据。
2)对相邻两个数据进行比较,看是否满足大小关系要求,若不满足让它俩互换。
3)一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。

冒泡排序的执行效率

最好情况下时间复杂度

最好情况为当要排序的数据已经是有序的,只需要进行一次冒泡排序,时间复杂度为O(n)。

最坏情况下时间复杂度

最坏情况为当要排序的数据是倒序的,我们需要进行n次冒泡操作,时间复杂度为O(n²)。

平均情况下时间复杂度

冒泡排序的平均情况下时间复杂度为O(n²)

对于包含 n 个数据的数组,这 n 个数据就有 n! 种排列方式。

不同的排列方式,冒泡排序执行的时间肯定是不同的。可以利用有序度和逆序度来分析。

有序度、无序度、满有序度

有序度是数组中具有有序关系的元素对的个数

有序元素对:a[i] <= a[j], 如果i < j。

反之就是无序度

逆序元素对:a[i] > a[j], 如果i < j。

完全有序的数组的有序度叫做满有序度,满有序度的元素对有n*(n-1)/2个。

2,4,3,1,5,6的有序度为11,满有序度为6*(6-1)/2=15, 可以得到:逆序度 = 满有序度 - 有序度

其实排序的过程也可以理解成一种增加有序度,减少逆序度的过程,最后达到满有序度,就说明排序完成了。

冒泡排序中每交换一次,有序度就+1

最坏情况下,初始状态的有序度是 0,所以要进行 n*(n-1)/2 次交换

最好情况下,初始状态的有序度是 n*(n-1)/2,就不需要进行交换。

我们可以取个中间值 n*(n-1)/4,来表示初始有序度既不是很高也不是很低的平均情况。

也就是说,平均情况下要进行 n*(n-1)/4 次交换操作,比较操作肯定要比交换操作多,而复杂度的上限是 O(n2),所以平均情况下的时间复杂度就是 O(n2)。

冒泡排序的内存消耗

冒泡排序的排序过程只涉及相邻数据的比较和交换操作,只需要常量级的临时空间,空间复杂度为O(1),属于原地排序。

冒泡排序的稳定性 

在冒泡排序中,只有交换才可以改变两个元素的前后顺序。

为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序,所以冒泡排序是稳定的排序算法。

冒泡排序的代码实现

public void bubbleSort(int[] a, int n) {
        if (n <= 1) return;
        for (int i = 0; i < n - 1; i++) {//外层循环:排好N个数据,需要排N-1次,每循环一次,排好一个数据
            boolean isExchange = false;
            for (int j = 0; j < n - 1 - i; j++) {  //内层循环,排好一个数据,需要比较N-1-i次
                                                  //i为已经循环过的次数(已经排好的数据个数)
                if (a[j] > a[j + 1]) {
                    int bigger = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = bigger;
                    isExchange = true;  //发生数据交换
                }
            }
            if (!isExchange) break;    //遍历未排序的部分,未发生数据交换,说明数组已经有序,跳出
        }
    }

冒泡排序的代码再优化

 思路:在每一轮排序后记录最后一次元素交换的位置,作为下次比较的边界,对于边界外的元素在下次循环中无需比较。

    public static void bubbleSort2(int[] a, int n) {
        if (n <= 1) return;
        // 最后一次交换的位置
        int lastExchange = 0;
        // 无序数据的边界,每次只需要比较到这里即可退出
        int sortBorder = n - 1;
        for (int i = 0; i < n - 1; i++) {
            boolean isExchange = false;
            for (int j = 0; j < sortBorder; j++) {
                if (a[j] > a[j + 1]) {
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                    // 发生数据交换
                    isExchange = true;
                    // 更新最后一次交换的位置
                    lastExchange = j;
                }
            }
            sortBorder = lastExchange;
            if (!isExchange) break;    // 没有数据交换,说明数组已经有序,跳出
        }
    }
发布了91 篇原创文章 · 获赞 22 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42006733/article/details/104381706