Java排序算法——冒泡排序(Bubble Sort)

冒泡排序是所有排序算法中最简单的一个排序,也是我个人学习的第一个排序方法,在这里重新进行一个总结。

冒泡排序(Bubble Sort)就如同其名称一样,水中的气泡由于压强的原因所以从下到上其大小也是从小到大,如下图:

整个排序过程分为一个大循环和大循环中的很多小循环进行,我们先来讲其中的小循环他做的事情:

每次小循环其实做的事情都很简单,就是单纯的循环所有数据找到其中最大值,将最大值放到当前比较数据的最后一个位置。下面给大家举个例子:

第一步,我们需要一个随机生成的数组,如下图:

 代码部分:

public static void main(String args[]){

    Random r = new Random();//申明并实例化一个Random对象
    int[] iArray = new int[7];//申明并实例化一个int数组用于测试排序
    for (int i = 0; i < iArray.length; i++) {
        //通过Random随机生成一个0(含)到50(不含)的数并插入对应位置
        iArray[i] = r.nextInt(50);
    }
    System.out.println(Arrays.toString(iArray));//通过方法输出数组结果

    //如果你不理解Arrays.toString(int[] a) 那就用下面这个循环 他们是一回事
    System.out.print("[");
    for (int i=0;i<iArray.length;i++) {
        System.out.print(iArray[i]);
        if(i==iArray.length-1){
            System.out.println("]");
        }
        else{
            System.out.print(", ");
        }
    }
}

小循环做的事情其实就是循环比较,第一步:将第[0]位和第[1]位数字进行比较若后面位置的数字比前面位置数字小,则交换两者位置,如下图:

由于"20“比”40“小,所以将数字进行交换,变成”20“在第[0]位,"40"在第[1]位,接下来就是需要比较的是第[1]位的"40"和第[2]位的"18",由于"18"比"40"小,所以交换两者的位置:

依此类推比较直到最后最后一位数字为止,如下图:

 可以看到,40在每一次比较之后都向后移了一位,从而从第一的位置到了最后,这样,我们就确定了整个数组中最大的数字。

第一轮的小循环比较就完全结束了,最终生成的结果为:

那么我们将上面的逻辑翻译成代码:

public static void main(String[] args) {

    //...以上为数据生成代码

    int temp;//临时存储用于交换数字用
    //内层小循环
    //由于逻辑中涉及iArray[i + 1]如果循环条件不-1,会多一次比较,并且会抛数组下表越界异常
    for(int i = 0;i<iArray.length-1;i++){
        //比较两个数据大小,如果前面的大则交换
        if(iArray[i]>iArray[i+1]){
            //交换逻辑 start
            temp = iArray[i];
            iArray[i] = iArray[i+1];
            iArray[i+1] = temp;
            //交换逻辑 end
        }
    }

    System.out.println(Arrays.toString(iArray));
}

 用上面的逻辑跑出来可以看到执行的结果已经将随机生成的数组中最大的那个数字移动到了最后一个位置。
 

接下来就要进行第二轮的比较了,第二的比较依旧是将第[0]位和第[1]位数字进行比较,不过有一点不一样的事情是之前是比较到整个数组的最后一个数字,而这次只需要比较到整个数组的倒数第二位数字(因为第一轮的小循环已经将最大的值放到了最后,无需比较最后一位数的大小,他肯定是最大的)。

第二轮的比较为:

 接下来就是第三轮...

依次类推,每次比较的终点位置都是数组长度减去已经执行的次数:

整体的执行效果如下图:

让我们把逻辑翻译成代码:

public static void main(String[] args) {
       
    //...以上为数据生成代码
    int temp;//临时存储用于交换数字用

    //外层循环,我们需要循环的总次数是总长度-1
    for(int j = 0;j<iArray.length-1;j++) {

        //内层小循环
        //逻辑中涉及iArray[i + 1]如果循环条件不-1,会多一次比较,并且会抛数组下表越界异常
        for (int i = 0; i < iArray.length - 1 -j; i++) {

            //比较两个数据大小,如果前面的大则交换
            if (iArray[i] > iArray[i + 1]) {

                //交换逻辑 start
                temp = iArray[i];
                iArray[i] = iArray[i + 1];
                iArray[i + 1] = temp;
                //交换逻辑 end

            }
        }
    }
    System.out.println(Arrays.toString(iArray));
}

 这里看到第二次循环条件中多了-1和-j,-1是因为5个数字我们只需要比较4次,-j的原因是每次比较的终点位置都是数组长度减去已经执行的次数。

以上就是常规的冒泡排序了,非常简单,我们可以稍微优化一下,比如假如一个数组在第一次循环就完成了,比如生成的数组是

[100, 1, 2, 3, 4]

这种情况只需要第一次循环就完成了排序,不需要第二次以及以后的循环。

所以我们可以在最开始新增一个标志位,如果没有进入过大小判断,那么我们直接所有跳出循环。

代码如下:

public static void main(String[] args) {
       
    //...以上为数据生成代码
    int temp;//临时存储用于交换数字用
    boolean flag;//新增一个旗帜用于判断是否循环已经完成

    //外层循环,我们需要循环的总次数是总长度-1
    for(int j = 0;j<iArray.length-1;j++) {
        
        //重置旗帜
        flag = true;

        //内层小循环
        //逻辑中涉及iArray[i + 1]如果循环条件不-1,会多一次比较,并且会抛数组下表越界异常
        for (int i = 0; i < iArray.length - 1 -j; i++) {

            //比较两个数据大小,如果前面的大则交换
            if (iArray[i] > iArray[i + 1]) {

                //交换逻辑 start
                temp = iArray[i];
                iArray[i] = iArray[i + 1];
                iArray[i + 1] = temp;
                //交换逻辑 end
                
                //发生过交换需要说明数组没完成排序
                flag = false;

            }
            //如果旗帜没有修改过,则可以直接跳出循环,节约时间
            if(flag){
                break;
            }    
        }
    }
    System.out.println(Arrays.toString(iArray));
}

引用一下个人查询到的相关gif,帮助大家总结一下(我实在找不到gif的作者,这个图用于学习真的很棒!感谢gif图作者)

 

好,我说完了,看到这里你应该明白这个排序了,这确实是非常简单的排序,我会在之后有空写更多的算法。

有什么疑问或者疑似我说错的地方的在评论区告诉我吧,看到后我会回复你。

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值