冒泡排序法。Java实现冒泡排序法

前言基础:

        1、冒泡排序法的时间复杂度为O(n2),空间复杂度为O(1),不需要额外的辅助空间。是一种稳定的排序算法。

        2、冒泡实质是不断两两比较,一旦两个相邻的元素是逆序的,就会交换这两个元素的位置,

最终进行n-1次这样的操作。

        3、每轮循环结束之后过后,保证了arr[n-i,n]是有序的,并且保证了倒数第i个元素呆在了该元素应该呆在的位置。下论循环后面这i个元素不再进入比较交换。

        4、每次排序之后,就会将整个数组的杂乱度减小,即减小逆序对的个数。

        5、外层循环i的含义:i不仅表示了循环的总轮数,而且i还表示已经排好序的元素个数。

排序过程


第一版本冒泡排序(最流行版本): 

    public static<E extends Comparable<E>> void Sort(E arr[]){
        //循环n-1次
        for (int i = 0; i < arr.length-1; i++) {
            Boolean flag=false; //当进行一次没有位置交换说明数组是有序的
            //后i个元素已经排好序,所以每次对[0,arr.length-i-1]进行排序
            for (int j=0;j<arr.length-i-1;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    Util.swap(arr,j,j+1);
                    flag=true;
                }
            }
            if  (!flag) break;
        }
    }


第二版冒泡排序(最终优化版本):

在第一版中我们发现如果对于321456这样的数组在第一次循环结束之后456就已经呆在了其应该呆在的位置,之后的循环就没有必要再在对这些元素进行遍历,于是根据i可以表示已经排好的元素个数这一性质进行了如下优化:

 

    public static<E extends Comparable<E>> void bestSort(E arr[]){
        //i不仅可以表示循环的次数,还可以表示已经排好序的元素个数
        //因为每次循环结束之后arr[n-i,n)是有序的
        for (int i = 0; i < arr.length-1; ) {
            Integer lastSwapIndex=0;
            for (int j=0;j<arr.length-i-1;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    Util.swap(arr,j,j+1);
                    lastSwapIndex=j+1;
                }
            }
            //下面的if语句可以直接省略,因为当没有进行交换的
            // 时候,lastSwapIndex=arr.length,for循环就会停止了
            // if (lastSwapIndex==0) break;
            i=arr.length-lastSwapIndex;
        }
    }


冒泡排序逆向版本(将之前的逆过来):

之前的冒泡都是正序的冒泡排序,每次排序保证了最大的元素依次在后面排开,下面的版本是每次保证了最小元素的有序,即arr[0,i)是有序的

    public static<E extends Comparable<E>> void SortReverse(E arr[]){
        for (int i=0;i<arr.length-1;){
            Integer flagIndex=arr.length;
            //保证arr[0,i]是有序的
            for (int j=arr.length-1;j>i;j--){
                if (arr[j].compareTo(arr[j-1])<0){
                    Util.swap(arr,j,j-1);
                    flagIndex=j-1;
                }
            }
            i=flagIndex;
        }
    }

全部代码整合的泛型设计:

public class BubbleSort {
    public BubbleSort(){}

    public static<E extends Comparable<E>> void Sort(E arr[]){
        //循环n-1次
        for (int i = 0; i < arr.length-1; i++) {
            Boolean flag=false; //当进行一次没有位置交换说明数组是有序的
            for (int j=0;j<arr.length-i-1;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    Util.swap(arr,j,j+1);
                    flag=true;
                }
            }
            if  (!flag) break;
        }
    }

    public static<E extends Comparable<E>> void bestSort(E arr[]){
        //i不仅可以表示循环的次数,还可以表示已经排好序的元素个数
        //因为每次循环结束之后arr[n-i,n)是有序的
        for (int i = 0; i < arr.length-1; ) {
            Integer lastSwapIndex=0;
            for (int j=0;j<arr.length-i-1;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    Util.swap(arr,j,j+1);
                    lastSwapIndex=j+1;
                }
            }
            //下面的if语句可以直接省略,因为当没有进行交换的
            // 时候,lastSwapIndex=arr.length,for循环就会停止了
            // if (lastSwapIndex==0) break;
            i=arr.length-lastSwapIndex;
        }
    }
    //实现每次确定最小元素的位置
    public static<E extends Comparable<E>> void SortReverse(E arr[]){
        for (int i=0;i<arr.length-1;){
            Integer flagIndex=arr.length;
            for (int j=arr.length-1;j>i;j--){
                if (arr[j].compareTo(arr[j-1])<0){
                    Util.swap(arr,j,j-1);
                    flagIndex=j-1;
                }
            }
            i=flagIndex;
        }
    }


    public static void main(String[] args) {
        Integer arr[]=Util.getRandomArr();
        //Integer arr[]={1,2,4,3};
        BubbleSort.SortReverse(arr);
        Util.Traverse(arr);
    }


}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值