【Java排序算法】冒泡排序及优化

冒牌排序:

       从数组开始元素向后两两比较,将大值向后移动。第一遍就会把最大值移动到数组最后,如此往复达到排序目的。

复杂度分析:

      比较次数n*(n-1)/2 次

      时间复杂度:O(n^2)

普通冒泡排序:

public static int[] BubbleSort1(int arr[],int len){
        for (int i = 0; i < len - 1; i++){
            for (int j = 0; j < len - 1 - i; j++){
                if (arr[j]>arr[j + 1]) {
                    //交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
            }
        }
        return arr;
    }

优化一:前有序优化

       因为每一次都会比较向后的所有元素,但是如果数组是{6,1,2,3,4,5}那么只需要一次交换数组就已经有序了,后面的几次比较都是无意义的,所以只要在交换的次数的上标记一下,下一次循环如果查不到这个标记就代表数组已经有序了,直接返回就可以了。

public static int[] BubbleSort2(int arr[],int len){
        for (int i = 0; i < len - 1; i++){
            int flag = 0;
            for (int j = 0; j < len - 1 - i; j++) {
                if (arr[j]>arr[j + 1]){
                    //交换
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = 1;//加入标记
                }
            }
            if (flag == 0){
                return arr;
            }
        }
        return arr;
    }

优化二:后有序优化

        对于后半部分有序的数组,我们可以记录一下从哪一位开始数组是有序的,这样下次遍历就不用遍历记录以后的了。

public static int[] BubbleSort3(int arr[],int len){
        int k = len - 1;
        for (int i = 0; i < len - 1; i++){
            int end = 0;//用来记录最后一次交换的位置
            int flag = 0;
            for (int j = 0; j < k; j++){
                if (arr[j]>arr[j + 1]){
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = 1;//加入标记
                    end = j;//交换元素,记录最后一次交换的位置
                }
            }
            if (flag == 0){
                return arr;
            }
            k = end;//下一次比较到记录位置即可
        }
        return arr;
    }

优化三:正反扫描

       正向扫描得到最大值放到最后面,反向扫描得到最小值放到最前面,达到一次扫描确定两个值的目的。

public static int[] BubbleSort4(int arr[],int len){
        int n = 0;//同时找最大值的最小需要两个下标遍历
        int k = len - 1;
        for (int i = 0; i < len - 1; i++)//确定排序趟数
        {
            int end = 0;
            int flag = 0;
            //正向寻找最大值
            for (int j = n; j < k; j++){
                if (arr[j]>arr[j + 1]){
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    flag = 1;//加入标记
                    end = j;//交换元素,记录最后一次交换的位置
                }
            }
            if (flag == 0){
                return arr;
            }
            k = end;//下一次比较到记录位置即可
            //反向寻找最小值
            for (int j = k; j > n; j--){
                int tmp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = tmp;
                flag = 1;
            }
            n++;
            if (flag == 0){
                return arr;
            }
        }
        return arr;
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值