简单的冒泡排序

在这里插入图片描述

在介绍冒泡排序之前,先介绍一下交换排序,如果 i<j 而 a[i]>a[j],即大的数排在小的数前面,称为 a[i] 和 a[j] 构成 逆序 。在排序的过程中,通过比较元素的大小 发现逆序就交换它们的位置,这样的排序方法称为:交换排序 。交换可以 消除 逆序。当所有的逆序都消除后,排序就完成了。或者说,没有逆序的序列就是有序序列 。其中 冒泡排序 和 快速排序 是典型的交换排序方法。

冒泡排序
冒泡排序也叫 气泡排序。基本的原理就是通过 反复的扫描数组,从数组 末尾开始比较两个 相邻元素a[i] 与a[i+1] 的大小,若 a[i]>a[i+1],就交换这两个值。并不断让 i- -(相当于让比较的两个相邻元素不断往前面移动,这样的话最终数组里面的 最小值就会交换到数组的 最前面),每比完一个循环,就是最小值已经送到了最前面,那么前面的最小值在接下来的循环就不会再去比较了(相对于 每一轮循环都将后面无序数组的最小值送入前面来)下面的图模拟了这样比较过程。

冒泡排序其实有 两种扫描方法,一种是上面图中描述的那样, 自下而上地扫描,称为 上升法可使 最小值上升到数组的开头。(就是从小到大排序)另一种便是 自上而下地扫描,称为 下降法,一遍扫描可使 最大值元素排到数组最末尾。(就是从大到小排序)。因为扫描过程中,总是习惯让大的元素排到数组后面(下降),小元素排数组前面(上升),酷似水中冒出的气泡,冒泡排序因此得名。下面来演示一下 使用Java语言来编写的简单冒泡排序算法。

在这里插入代码片import java.util.Arrays;import java.util.Arrays;
    public class MaoPao_JianDanPaiXu {
        public static void main(String[] args) { 
            // 打印一下没排序之前的数组值顺序
            int[] a = new  int[] {4,6,3,9,8,7}; 
            System.out.print("排序之前的元素顺序:");
            // 使用 PaiXun() 方法排序一下后再打印 PaiXun(a);
            System.out.println(Arrays.toString(a));
            System.out.print("排序之后的元素顺序:");
            System.out.println(Arrays.toString(a));
        } 
        public static void PaiXun(int[] a) { 
            int k,n=0; // 临时中间变量 
            for(int i=0;i<a.length-1;i++) {
                for(int j=a.length-2;j>=i;j--) { 
                    if(a[j]>a[j+1]) {
                        // 调换如果“逆序”调换两个值的顺序 
                        k = a[j]; 
                        a[j]=a[j+1]; 
                        a[j+1]=k; 
                    } 
                } 
                n++; 
            } 
            System.out.println("本次扫描了:"+n+"次");
        }
    }

输出结果:排序之前的元素顺序:[4, 6, 3, 9, 8, 7] 本次扫描了:5次排序之后的元素顺序:[3, 4, 6, 7, 8, 9] 当然如果想改成从大到小排序只要把if语句里面的>号改成<号就可以了,不过这种排序算法的 效率是 非常低的。因为不管原始的数组里面的数据排列情况如何,算法的外循环都执行了a.length-1次,这种扫描方式是一种全局扫描方式。实际上,如果在某一遍的扫描中 没有发现逆序(也就是没有元素交互位置),那不就说明全部元素已经排序好了,没有必要再接着循环了,可以结束排序了。根据这一思想,我们可以使用一个 交互吗 标记 flag,来 记录本次扫描是否发生过元素交换。根据 flag 的值是 true 还是 false 决定是否还要进行下一次的循环。下面给出了一个示例图。

根据以上改进的算法如下所示:

在这里插入代码片import java.util.Arrays;import java.util.Arrays;
    public class MaoPao_JianDanPaiXu {
        public static void main(String[] args) { 
            int[] a = new  int[] {4,6,3,9,8,7};
    
            // 打印一下没排序之前的数组值顺序  
            System.out.print("排序之前的元素顺序:"); 
            System.out.println(Arrays.toString(a)); 
    
            // 使用 PaiXun() 方法排序一下后再打印
            PaiXun(a); 
            System.out.print("排序之后的元素顺序:"); 
            System.out.println(Arrays.toString(a));
        } 
        public static void PaiXun(int[] a) { 
            int i,k,n=0; // n是记录外循环的次数 
            i=a.length-2; 
            boolean flag = true; 
            while(flag) { 
                flag = false; // 每次进入循环把flag的值设为假 
                for(int j=0;j<=i;j++) { 
                    // 该次扫描调换了元素,又把flag设为真
                    if(a[j]>a[j+1]) { 
                        k = a[j]; 
                        a[j] = a[j+1]; 
                        a[j+1] = k; 
                        flag = true; 
                    } 
                    i--; 
                } 
                n++; 
            } 
            System.out.println("本次排序扫描了:"+n+"次"); 
        }
    }

输出结果:排序之前的元素顺序:[4, 6, 3, 9, 8, 7] 本次排序扫描了:3次排序之后的元素顺序:[3, 4, 6, 9, 8, 7] 不出所料,本来要扫描5遍的变成了3遍。效率比之前的好了些。如果是在数据量很大的情况下还是蛮有改善的。( 注意!扫描的次数不是排序总循环的次数 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值