用最土的方式把细节剖给你看——冒泡排序算法的 Java 实现版

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

说到算法,很多人都会害怕。但是想升职加薪怎么办呢?

总是逃避是改变不了什么,也解决不了什么问题。我不希望自己以后一直被这些算法堵住,但同时也不强求一下子掌握优雅的实现算法。

一点一点地吃透它。

冒泡排序的概念:

不断的比较相邻的元素,如果顺序不对,就交换。 一轮又一轮,直到所有相邻的元素都比较完,是一种非常朴素的排序方法。

摆平心态放大招


import java.util.Arrays;

public class 冒泡算法 {
    // 优化点:挨个比较了一圈,没有交换,说明已经排好了;已经有序的不要去交换了
    public static void main(String[] args) {
        int[] values = {3, 1, 6, 2, 9, 0, 7, 4, 5, 8};
        bubbleSort(values);
        System.out.println(Arrays.toString(values));
    }

    private static void bubbleSort(int[] values) {
        int temp;
        for (int i=0; i<values.length; i++) {
            for (int j = 0; j<values.length-1-i; j++) { 
                if (values[j] > values[j+1]) {  // 这一行决定了是从小到大,还是从大到小
                    temp = values[j];
                    values[j] = values[j+1];
                    values[j+1] = temp;
                }
                System.out.println(i + ": " + Arrays.toString(values));
            }
            System.out.println();
        }

    }
}
复制代码

我手敲了基础实现版后,还加了很多 print,把过程复现,然后理解程序的每一句话实现了什么,改变了什么,就会更容易理解一些。

  1. 核心实现部分,嵌套循环,挨个比较:

image.png 这一行可以看到 values[j]values[j+1] 分别是前一个元素和后一个元素。我文章里用的是前一个大于后一个的话,就交换,也就是把前一个元素往后堆,循环这个过程,就很像泡泡。一个一个这样冒到最后。

最后的排序结果:

image.png

  1. 这里 j 的上界没有取 values.length, 就是因为每次冒过去,最大值已经排到最后了。

image.png

  1. 我们来仔细看看,每个循环内做了什么样的事情:
  • 第一个循环:

image.png 第一个循环,一共 0-9,10个元素,两两比较,比较 9 次。

  • 第二个循环,最后两个肯定比较好了,少一次比较:

image.png

  • 第三个循环:

image.png

  • 第四个循环:

image.png

  • 第五 ~ 第九个循环:

image.png

也就是这个时候,你是不是明白了,为什么那么多调优文章都说,有重复的了吧?

到这里看起来已经非常棒了,上面我们已经对冒泡的次数,以及每次冒泡需要比较的次数都做了优化,但这就够了嘛,不 我们还可以对比较的次数做进一步的优化,每轮冒泡时,最后一次交换的索引可以作为下一轮冒泡比较的次数,如果这个值是 0, 就证明整个数组有序,直接退出外层循环即可。「非正经程序员 juejin.cn/post/701632…

优化了!

上面的截图已经很清楚地表现了代码可以优化的地方:

让这个循环在有序的情况下别比较了。

private static void bubbleSort(int[] values) {
    int temp;

    for (int i=0; i<values.length; i++) {
        boolean flag = true;
        for (int j = 0; j<values.length-1-i; j++) {
            if (values[j] > values[j+1]) {
                temp = values[j];
                values[j] = values[j+1];
                values[j+1] = temp;
                // 发生交换了,就改变,数组在这一趟是无序的,还要接着比较
                flag = false;
            }
            System.out.println(i + ": " + Arrays.toString(values));
        }
        // 内循环都跑完了,flag 还是 true,说明已经有序了,后面不用再比较了
        if (flag) {
            break;
        }
        System.out.println();
    }

}
复制代码

我们是通过新增了一个布尔变量实现的: image.png

重新跑一次以后发现,前面的循环和之前都一样,不同的是排好序以后,就不再进行多余的比较了:

image.png

彩蛋:

www.geeksforgeeks.org/bubble-sort…

猜你喜欢

转载自juejin.im/post/7018198518343041061