冒泡排序Java实现以及时间复杂度分析

冒泡排序Java实现以及时间复杂度分析

Java实现

public class BubboSort_01 {

    public static void main(String[] args) {
        int[] num={3,1,5,2,5,6,12,8,9};
        BubboSort(num);
        System.out.println(Arrays.toString(num));
    }

    public static void BubboSort(int[] arr){

        int lastExchangeIndex=0;            //上次交换的最后的位置
        int sortBorder= arr.length-1;       //有序边界

        for (int i=0;i

从代码中分析几个问题
冒泡排序是原地排序算法吗?
冒泡排序的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,因此,空间复杂度为O(1),是一个原地排序算法。

冒泡排序是稳定排序算法吗?
在冒泡排序中,只有交换才可以改变两个元素的前后顺序。为了保证冒泡排序的稳定性,在冒泡的过程中,我们对两个大小相等的相邻的元素不做交换,这样就能保证相同大小的元素,在排序前后原有的先后顺序不会改变,因此,冒泡排序是稳定排序。

时间复杂度分析

在最好的情况下,待排序的序列已经有顺序的了,所以只需要比较一次就可以,这个时候的时间复杂度为O(1);在最坏的情况下,待排序的序列恰好是倒序的,这个时候需要进行n次冒泡,而每次冒泡需要比较n个元素(这个随者已排好序列的增加而减少,但一般都看作是n个元素),所以时间复杂度为O(n^2)。
重点来了,平均时间复杂度是多少呢?
这里使用一种简单,不是非常严谨的方法来计算。
首先需要明白什么是有序度,什么是逆序度
有序度是指数组中具有有序关系的元素对的个数,如果用数字表达式表示出来,就是a[i]<=a[j],i<=j;如下图:
冒泡排序Java实现以及时间复杂度分析_第1张图片
逆序度的定义正好与有序度相反,是指数组中逆序元素对的个数,而逆序元素对的定义也与有序元素对正好相反,即:a[i]j。
对于一个倒序(假设从小到大为有序)排列的数组,如 [6,5,4,3,2,1],有序度是0,逆序度是n*(n-1)/2,也就是15;对于一个完全有序的数组,如[1,2,3,4,5,6],有序度是n*(n-1)/2,也就是15,逆序度是0。我们把完全有序的数组的有序度称为满有序度(也就是n*(n-1)/2)。满序度,逆序度以及有序度之间有一定的关系:逆序度=满序度-有序度。排序的过程就是增加有序度、减少逆序度的过程。当最终达到满序度的时候,就是有序的了。
假设待排序的数组的初始状态是[4,5,6,3,2,1],其中,有序元素对有(4,6)、(4,5)、(5,6),因此有序度为3,而满有序度则为n*(n-1)/2=15。
冒泡排序过程包含两个操作:比较和交换。因为冒泡排序只会交换相邻的两个元素,所以每进行一次交换操作,有序度就会增加1,因此,无论冒泡排序算法怎样改进,总交换次数是确定的,即为逆序度,也就是n*(n-1)/2减去初始有序度,在上面的序列中,要交换的次数则为15-3=12。

那么,对于包含n个数据的数组进行冒泡排序,平均交换次数是多少呢?

在最坏的情况下,初始状态的有序度是0,因此要进行n*(n-1)/2次交换。在最好的情况下,无须交换。那么我们就可以去中间值n*(n-1)/4,用它表示初始有序度既不是很高,也不是很低的平均情况。换句话说,在平均情况下,需要n*(n-1)/4次交换操作,也就是说,交换操作次数n^2量级的。而比较操作肯定要比交换操作多,复杂度的上限又是O(n ^ 2),因此,比较操作次数也是n ^ 2量级的。综合比较和交换两部分操作,冒泡排序平均情况下的时间复杂度为O(n^2)。

你可能感兴趣的:(数据结构与算法,java,排序算法,算法)