排序-----冒泡排序及其优化(java)

原理:冒泡排序可就是通过冒泡泡的方式,每一趟把最大的数字通过冒泡泡的方式放到最后。也就是如果有n个数字,一趟排序完成后,最大的数字就在最后,那么接下来就只用对前边的n-1项数字进行排序

算法描述

1)如果有n个数要进行排序,那么只需要进行n-1趟排序

2)第一趟排序:通过相邻数字进行两两比较,如果前一个数比后一个数大,就进行交换。这一趟排序完成后,最大的数就在最后一位,接下来只需要对他的前n-1项进行排序。

3)第二趟排序:对前n-1项进行排序,两两比较,如果前一个数比后一个数大交换两数的位置,这一趟排序完成后,最大的数就排在倒数第二的位置上。,接下来就对前边n-2项进行排序

4)直到还有一个元素的时候就说明排序完了,

基本方法:用两层循环,外层决定排序的趟数,内层决定每层里面比较的次数,然后如果前一个数比后一个数大,就进行交换

 public static void bubbleSort(int[] arr,int len) {
        for(int i=0;i<len-1;i++){//外部循环
            for(int j=0;j<len-i-1;j++){//内部循环
                if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j+1]=tmp;
                }
            }
        }
    }

优化方法1:添加标记flag,来判断有没有进行交换,如果一趟下来都没有进行交换,那么说明元素都已经有序了,就不需要进行排序了。它减少了多余的排序次数

public static void bubbleSort2(int[] arr,int len) {
        for(int i=0;i<len-1;i++){//外部循环
            int flag=0;//添加的标记
            for(int j=0;j<len-i-1;j++){//内部循环
                if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j+1]=tmp;
                    flag=1;//如果交换了,就把标记修改为1
                }
            }
            if(flag==0){//如果没有进行交换,就说明排序已经完成
                break;
            }
        }
    }

优化方法2:记录交换的位置,如果交换位置为0的时候就说明排序完成

public static void bubbleSort3(int[] arr,int len) {
        for(int i=0;i<len-1;i++){//外部循环
            int pos=0;//记录最开始的交换位置
            for(int j=0;j<len-i-1;j++){//内部循环
                if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j+1]=tmp;
                    pos=j;//如果交换了,就把交换位置修改为j
                }
            }
            if(pos==0){//如果pos==0,就说明排序已经完成
                break;
            }
        }
    }

优化方案3:每一趟不仅可以把最大的数冒泡泡到最后相应的位置,也可以把最大的数冒泡泡到前边对应的位置,也就是同时排序,它是减少了排序的趟数

 public static void bubbleSort4(int[] arr,int len) {
        for(int i=0;i<len-1;i++){//外部循环
            int flag=0;//添加的标记
            for(int j=0;j<len-i-1;j++){//内部循环
                if(arr[j]>arr[j+1]) {//如果前一个数比后一个数大的话就进行交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j+1]=tmp;
                    flag=1;//如果交换了,就把标记修改为1
                }

            }
            for(int z=0;z<len-i-1;z++){
                if(arr[z+1]<arr[z]) {//如果后一个数比前一个数小的话就进行交换
                    int tmp = arr[z];
                    arr[z] = arr[z + 1];
                    arr[z+1]=tmp;
                    flag=1;//如果交换了,就把标记修改为1
                }
            }
            if(flag==0){//如果flag==0,就说明排序已经完成
                break;
            }
        }
    }

时间复杂度:

冒泡排序的的平均和最坏的情况下时间复杂度都为O(n2),最好的情况下为O(n),也就是本身是有序的

空间复杂度:O(1)

稳定性:因为冒泡排序它是把大的往后调,或者把小的往前调,所以都是相邻之间的元素进行比较,交换也发生在相邻的元素之间,如果相邻的元素不满足交换的条件,他们就不会进行交换,所以即使相同元素,他们之间的顺序都不会发改变。

猜你喜欢

转载自blog.csdn.net/qq_40955824/article/details/89604970