Java基础算法(4)——冒泡排序

Java基础算法(4)——冒泡排序

1.冒泡排序思想与原理简述

冒泡排序是一种最简单的交换排序,通过相邻元素两两比较,如果逆序(若需排为升序,则逆序是前者大于后者),则进行交换,使得大的元素像气泡一样逐渐往上(升序即大元素右移)。

每次遍历都把最大值排到了未排序序列的最后

需要遍历(排序)的次数:数组长度-1 (最后就剩一个元素了,不需要再排序了)

(简单说:第n次排序,都是把第n大的数,排在倒数第n位)

2.完整代码实现(含注释)

简洁版

    //简洁版
    int N = a.length;
        for (int i=0;i<N-1;i++){
        for (int j=0;j<N-1-i;j++){
            if (!less(a[j],a[j+1])) {
                exch(a,j,j+1);
            }
        }
    }

详细版(含注释,运行样例)

与上一篇文章选择排序类似,继承排序类模板类Template

Java基础算法(1)——选择排序

package Algorithm.Sort;

/**
 * 排序(4)
 * 冒泡排序
 * 以升序为例:前面的数大于后面的数则交换这两个数的位置
 * 排序次数 数组长度-1
 * 每次遍历都把最大值排到了未排序序列的最后
 * (简单说:第n次排序,都是把第n大的数,排在倒数第n位)
 */
public class BubbleSort extends Template{
    //升序
    public static void sort(Comparable[] a) {
        int N = a.length;//数组长度
        for (int i=0;i<N-1;i++){
            for (int j=0;j<N-1-i;j++){
                if (!less(a[j],a[j+1])) {//a[j]>a[j+1]则交换
                    exch(a,j,j+1);
                }
            }
            System.out.println("第"+(i+1)+"次遍历结果,把第"+(i+1)+"大的数,排在倒数第"+(i+1)+"位");
            show(a);
        }

    }

    public static void main(String[] args) {
        String[] a = {"c", "s", "d", "n", "x", "i", "n", "g", "w", "e", "i","s","h","e","l","l","s","o","r","t"};
        System.out.println("冒泡排序前");

        show(a);
        sort(a);

        assert isSorted(a);
        System.out.println("冒泡排序后");
        show(a);
    }
}

3.运行效果

冒泡排序前
c s d n x i n g w e i s h e l l s o r t

冒泡排序后
c d e e g h i i l l n n o r s s s t w x

详细过程(每次遍历,都打印一遍结果)

冒泡排序前
c s d n x i n g w e i s h e l l s o r t
第1次遍历结果,把第1大的数,排在倒数第1位
c d n s i n g w e i s h e l l s o r t x
第2次遍历结果,把第2大的数,排在倒数第2位
c d n i n g s e i s h e l l s o r t w x
第3次遍历结果,把第3大的数,排在倒数第3位
c d i n g n e i s h e l l s o r s t w x
第4次遍历结果,把第4大的数,排在倒数第4位
c d i g n e i n h e l l s o r s s t w x
第5次遍历结果,把第5大的数,排在倒数第5位
c d g i e i n h e l l n o r s s s t w x
第6次遍历结果,把第6大的数,排在倒数第6位
c d g e i i h e l l n n o r s s s t w x
第7次遍历结果,把第7大的数,排在倒数第7位
c d e g i h e i l l n n o r s s s t w x
第8次遍历结果,把第8大的数,排在倒数第8位
c d e g h e i i l l n n o r s s s t w x
第9次遍历结果,把第9大的数,排在倒数第9位
c d e g e h i i l l n n o r s s s t w x
第10次遍历结果,把第10大的数,排在倒数第10位
c d e e g h i i l l n n o r s s s t w x
第11次遍历结果,把第11大的数,排在倒数第11位
c d e e g h i i l l n n o r s s s t w x
第12次遍历结果,把第12大的数,排在倒数第12位
c d e e g h i i l l n n o r s s s t w x
第13次遍历结果,把第13大的数,排在倒数第13位
c d e e g h i i l l n n o r s s s t w x
第14次遍历结果,把第14大的数,排在倒数第14位
c d e e g h i i l l n n o r s s s t w x
第15次遍历结果,把第15大的数,排在倒数第15位
c d e e g h i i l l n n o r s s s t w x
第16次遍历结果,把第16大的数,排在倒数第16位
c d e e g h i i l l n n o r s s s t w x
第17次遍历结果,把第17大的数,排在倒数第17位
c d e e g h i i l l n n o r s s s t w x
第18次遍历结果,把第18大的数,排在倒数第18位
c d e e g h i i l l n n o r s s s t w x
第19次遍历结果,把第19大的数,排在倒数第19位
c d e e g h i i l l n n o r s s s t w x
冒泡排序后
c d e e g h i i l l n n o r s s s t w x

4.冒泡排序简单优化

优化缘由:

观察上述冒泡排序详细过程可知,在第十次其实就已经排好了(第十次结果字体加粗了,便于查看)。

因此,后面几次的遍历(排序)其实并没有交换元素位置。

优化方案:

设立一个标识变量,用于鉴别本次遍历(排序)中是否有交换过元素位置

标识变量常用Boolean类型的true/false,或者用int类型0/1表示(当然其他的也行)。

假设标识变量定义如下:

boolean flag=false;

//设置标识变量,标识本次遍历中是否有元素交换

// (flag默认为true,代表为没有交换过)

当本次遍历没有发生元素交换时,即标识变量为false,则跳出循环,结束遍历,以为此时数组已经有序。

具体代码如下(含注释):

    //升序(简单优化后)
        public static void sort(Comparable[] a) {
            int N = a.length;//数组长度
            boolean flag=false;//设置标识变量,标识本次遍历中是否有元素交换
            // (flag默认为true,代表为没有交换过)
            for (int i = 0; i < N-1; i++) {
                for (int j = 0; j < N - 1 - i; j++) {
                    if (!less(a[j], a[j + 1])) {//a[j]>a[j+1]则交换
                        exch(a, j, j + 1);
                        flag=true;//交换过元素
                    }
                }
                System.out.println("第" + (i + 1) + "次遍历结果,把第" + (i + 1) + "大的数,排在倒数第" + (i + 1) + "位");
                show(a);
                if(!flag){//若本次遍历中没有发生元素交换,则数组已经排序好,退出循环
                    break;
                }else {
                    flag=false;
                }
            }
        }
        

优化后的运行效果:

冒泡排序前
c s d n x i n g w e i s h e l l s o r t 
第1次遍历结果,把第1大的数,排在倒数第1位
c d n s i n g w e i s h e l l s o r t x 
第2次遍历结果,把第2大的数,排在倒数第2位
c d n i n g s e i s h e l l s o r t w x 
第3次遍历结果,把第3大的数,排在倒数第3位
c d i n g n e i s h e l l s o r s t w x 
第4次遍历结果,把第4大的数,排在倒数第4位
c d i g n e i n h e l l s o r s s t w x 
第5次遍历结果,把第5大的数,排在倒数第5位
c d g i e i n h e l l n o r s s s t w x 
第6次遍历结果,把第6大的数,排在倒数第6位
c d g e i i h e l l n n o r s s s t w x 
第7次遍历结果,把第7大的数,排在倒数第7位
c d e g i h e i l l n n o r s s s t w x 
第8次遍历结果,把第8大的数,排在倒数第8位
c d e g h e i i l l n n o r s s s t w x 
第9次遍历结果,把第9大的数,排在倒数第9位
c d e g e h i i l l n n o r s s s t w x 
第10次遍历结果,把第10大的数,排在倒数第10位
c d e e g h i i l l n n o r s s s t w x 
第11次遍历结果,把第11大的数,排在倒数第11位
c d e e g h i i l l n n o r s s s t w x 
冒泡排序后
c d e e g h i i l l n n o r s s s t w x 

可以看到遍历了11次,而优化前遍历了19次。

在这个例子中为什么是遍历11次呢,因为第10次遍历完后已经排序好了,因此第11次遍历中没有发生交换,标识变量为false,会退出遍历的循环。

发布了67 篇原创文章 · 获赞 32 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42391904/article/details/100679364
今日推荐