美文网首页web前端jsH5学习笔记
深入浅出“冒泡排序”

深入浅出“冒泡排序”

作者: MR_LIXP | 来源:发表于2016-08-31 17:02 被阅读546次

    请各位读者添加一下作者的微信公众号,以后有新的文章,将在微信公众号直接推送给各位,非常感谢。


    0.前言

    冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
    它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
    走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
    这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名。

    正如百度百科中的所说,我们的冒泡排序是一种非常基础的一种算法,虽然在日常的工作中的使用的情况较少,但是由于其入门简单,逻辑清楚,还是非常适合初学者作为一个基础算法的入门,所以我们今天就一起来看一看,冒泡排序到底是怎么回事。

    下面引用一下知乎用户可可的话术

    想想有一群泡泡
    其中一个泡泡跑到一个泡小妹说,小妹小妹你过来咱俩比比谁大,小妹说哇你好大,于是他跑到了泡小妹前面,又跟前面的一个泡大哥说,大哥,咱俩比比谁大呗。泡大哥看了他一眼他就老实了。这就是内层的for,那个泡泡跟每个人都比一次。
    话说那个泡泡刚老实下来,另一个泡泡又开始跟别人比谁大了,这就是外层的for,每个泡泡都会做一次跟其他泡泡比个没完的事。

    注意,以下代码部分由 JS 代码进行展示。

    1.如何实现排序

    既然我们想要进行排序,那么我们首先必须要有一个基础的数组,然而这个数组的情况可能会存在很多种,这里我们暂时只讨论最复杂的情况。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        // 声明一个最糟糕情况的数组
        var arr = [9,8,7,6,5,4,3,2,1];
    </script>
    </html>
    

    注意,我在这里声明了一个非常糟糕的数组,也就是说,数组中的每一个内容都需要进行排序。

    既然我们有了这么一个基础的数组,我们就可以正式开始对我们的内容进行排序了。

    根据冒泡排序的思想,我们每一次循环,都将数组中最大的那个数字,放在数组的最后。

    这样就可以保证我们的数组中,每次循环中的最大的那个都在后面,这样全部循环一次之后,我们的内容也就全部排序完毕了。

    具体实现可以参考下面的图片。

    第一次循环的时候,将数组中最大的那个内容放在程序的最后面。

    这是我们第一次交换数组中内容,那么我们交换了几次呢?

    我们总共交换了 8 次。

    因为倒数第二次的时候,我们的 1 和 9 就已经排序完毕了,而最后的数字 9 不需要我们再交换一次,所以最后交换次数是 8 次。

    而第二次交换呢?

    我们同样需要将数组中最大的哪一个数字挪动到数组的最后一位,这个时候,我们需要挪动几次呢?

    我们的交换次数相比于上面的情况再次减少一次,现在总共挪动了 7 次。

    以此类推,我们可以想象出来,挪动的次数应该如同下面这张图一样。

    我们的数组长度为 9。

    我们外层的循环数,第一次将数组中最大的一位数字挪动到最后面,第二次挪动第二大的数字,第三次第三大数字,……,直到我们最后将所有的内容全部挪动完毕。

    那么我们可以得出一个结论,我们需要挪动的次数是 数组的长度 - 1 次。

    也就是说,我们可以去使用一个循环。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var arr = [9,8,7,6,5,4,3,2,1];
        // 外层控制的循环的次数,看我这里需要循环几次
        for(var i = 0; i < arr.length - 1; i++){
            document.write('<br>');
        }
    </script>
    </html>
    

    我们知道了我们这个数组需要循环几次,那么我们现在怎么控制我们需要在内部需要挪动几次呢?

    这时候我们就要使用到内部的一层循环了。

    我们可以在我们内层的循环中去控制我们的程序中间需要挪动几次。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var arr = [9,8,7,6,5,4,3,2,1];
        // 外层控制的循环的次数,看我这里需要循环几次
        for(var i = 0; i < arr.length - 1; i++){
            // 内层控制数组内的循环次数
            for(var j = 0; j < arr.length -i -1; j++){
                document.write(arr + '<br>');
            }
            document.write('<br>');
        }
    
    </script>
    </html>
    

    这时候我们就已经将我们的数组中每一个元素都能依次查找到了,可是我们的冒泡循环不是为了进行排序么?

    这时候我们需要将大的数字挪动到后面。

    那么我们该怎么做呢?

    我们需要将两个元素进行交换,那么怎么交换呢?

    我们可以再次声明一个变量,这样将两个数字进行交换了。

                // 进行内容的交换
                if(arr[j] > arr[j + 1]){
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
    

    这时候我们将之前的所有的内容进行合并,我们可以通过双重循环,将前后的数字和在它后面的数字进行交换。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    
    </body>
    <script type="text/javascript">
        var arr = [9,8,7,6,5,4,3,2,1];
        // 外层控制的循环的次数,看我这里需要循环几次
        for(var i = 0; i < arr.length - 1; i++){
            // 内层控制数组内的循环次数
            for(var j = 0; j < arr.length -i -1; j++){
                // 进行内容的交换
                if(arr[j] > arr[j + 1]){
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
                document.write(arr + '<br>');
            }
            document.write('<br>');
        }
    
    </script>
    </html>
    

    这样当我们循环结束之后,我们的数字也就正好全部替换完成了。

    2.后续

    其实我们现在表示的,是冒泡排序中最糟糕的情况,每一个数字都需要进行交换,但是我们日常工作中可能不是所有的数字都需要进行排列。

    有一部分的数字已经是全部排序好的,这时候我们不需要完全进行排序。

    那该怎么办呢?

    其实我们可以去定义一个变量,专门用于记录当前这个循环是否进行了循环,如果当前内层循环中,一次交换也没有发生,那么是不是就证明我们这个序列已经排序完毕了呢?

    这样我们就可以去判断我们的变量,去看看我们的循环是否可以结束。

    今天时间有限,就不去书写具体的代码了,大家可以在网上简单搜索一下,冒泡排序优化,自己试着去看看,怎么去将这个东西进行优化吧!~

    相关文章

      网友评论

      本文标题:深入浅出“冒泡排序”

      本文链接:https://www.haomeiwen.com/subject/chpzsttx.html