冒泡排序

一、思路

  在进行冒泡排序(升序)时,需要将数组中的元素(len)两两进行比较,如果前面的元素大于后面的元素的话,则交换两个数,否则,比较下一个元素和它下一个元素的大小,依次执行,执行一次循环结束之后,可以找到当前数组中最大的一个元素,将其排到了最后面,然后问题规模变小,然后找出len-1个元素里的最大值,使之成为第二大元素,依次执行,需要在外层嵌套一层循环。

二、优化

  如果数组中的数据已经是排好序的,那么就不需要遍历那么多次了,定义一个标志位,如果没有执行交换,如果一轮下来没有进行数据交换,则证明数据已经拍好顺序了,此时,则直接跳出循环。

三、图解

  

四、代码实现

  有数组int arr[] = {23,19,33,55,27},按照小到大的顺序排序

  两种思路

  思路一、arr[i]与arr[i+1]比较,如果前者比后者大,则交换二者的位置,这样两两调换后,一轮下来,最大的会被放到arr[len-1]的位置。每一轮i都从0开始,当第j轮排序之后就有最后面的j个数字,因为它是最大的,所以每轮的最后都不用理他了,也就是 arr.length-1-j 往后的数就不用管了,比如第一轮开始的时候,数组共有四个数字,j=0,那么 arr.length-1-j =4,也就是说下表3以后的就可以不用管了,因为下表4以后,没有数字,所以,第一轮所有的数字都要参与比较,第二轮开始的时候,已经比较结束一轮了。此时j=1,所以 arr.length-1-j = 3,也就是说下表3之后的元素都不用管了,已经是最大的了,因为两两比较之后55会到arr[4]的位置。

public static int[] sort(int[] arr){
        //外层决定比较的轮数
        for (int i = 0;i < arr.length -1;i++){
            //内层决定每轮比较的次数
            for (int j = 0;j < arr.length -1 -i;j++){
                //小->大
                if (arr[j] > arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        return arr;
    }

  思路二、从后往前比较。也就是说先用27跟55比较,再跟33比较,再跟19比较,再跟23比较,发现19是最小的,将其放到最前面(index=0)的位置,然后j=1,也就是第二轮,就不用看下标为0了,因为它是最小的了,然后接着比较

public static int[] sort2(int[] arr){
        //外层决定比较的轮数
        for (int i = 0;i < arr.length-1;i ++){
            //从后往前比较,倒数第二个与倒数第一个比较,所以这里j=arr.length-2
            for (int j = (arr.length - 2); j >= i;j--){
                if (arr[j] > arr[j+1]){
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
        return arr;
    }

注:这里的j为什么等于arr.length-2呢?因为length=5,我最多让下标2和下标3的数字比较(j+1最大等于3),也就是j最大等于2,2和2+1比较,然后0和1比较。

五、时间复杂度分析

    最好的情况下时间复杂度为0(n):当待排序的数据已经按照顺序排好的情况下

  最坏的情况下时间复杂度为0(n^2):因为要比较n-1趟,每一趟要比较(n-1-i)次

原文地址:https://www.cnblogs.com/Gxiaobai/p/10486689.html