zoukankan      html  css  js  c++  java
  • 排序基础(插入排序和选择排序)

    (以下代码均以javascript实现)

    选择排序:

    首先来介绍一下选择排序,假如我们有一个数组[1,4,7,2,5,9]。

    1、现在我们选择出这个数组中最小的数,和下标为0的数作交换。从数组中看就是1,所以不用做交换了。

    2、剩下[4,7,2,5,9],我们从这里面选出最小的数,和原数组下表为1的数作交换。交换后即[2,7,4,5,9]。第二次交换完成后,数组为[1,2,7,4,5,9]。

    ......

    我们就是不断的在剩下数组中找到最小的数,然后和对应的数进行交换。在这个算法中,我们要进行双循环,并且每次都是循环到底。

    代码如下:

    function SelectSort( arr ){        
        if(Object.prototype.toString.apply(arr) === "[object Array]"){
           //开始进入循环
            for(let i = 0; i < arr.length; i++){
           //标记查询索引
                    let MinInt = i;
                    let temp = null;
            for(let j = i + 1; j < arr.length; j++){
               //判断大小
                if( arr[j] < arr[MinInt]){
                  //如果有比MinInt更小的数就更换索引
                    MinInt = j;
                }
              }
    
                   if( i !== MinInt){ //如果最小数是本身不做交换
                        temp = arr[MinInt];
                        arr[MinInt] = arr[i];
                        arr[i] = temp;
                    }
    
             }
        }
                        
        }       

    选择排序算法很简单,我们只需要流程是什么样就可以立刻写出代码,接下来我们看插入排序。

    插入排序就像摸牌,一开始你的手上没有牌,抽取第一张牌放到手里,抽取第二张的时候你要和第一张做对比,如果比第一张大就放到第一张后面,如果比第一张小就放到第一张的前面。然后继续摸第三张牌,分别和前面两张作对比,然后这样继续下去。

    接下来我用数组来详细说:我们有一个数组[1,7,4,2,5,9]

    1、首先我们摸第一张牌1放到手里;

    2、然后摸第二张牌7,和1做比较,发现7更大,那么就放到1的后面不做交换;

    3、摸第三张4,和7比较更小,那么4和7做交换;然后4再和1做比较,比1更大,那么不做交换;第三次摸牌结果为[1,4,7,2,5,9];

    ......

    接下来都是一样的,当前一个数比摸的牌更大,就做交换,当遇到比摸的牌更小的数,就可以不动了,因为手上的牌都是已经排序的,如果有一个数比手上的数更小,那么它前面的数肯定比手上的数更小。

    按照这种逻辑思路,我们来写出代码:

    for(let i = 1; i < arry.length; i++){
        //开始摸第一张牌
         for(let j = i; j > 0; j--){
            //和手上的牌进行对比,如果更小就进行交换
        if(arry[j]>arry[j-1]){
           let temp = arry[j];
           arry[j] = arry[j-1];
            arry[j-1] = temp;
                
        }else{
            break;
        }
    }

    我们来对比一个选择排序算法和插入排序算法,通过console.time("xxx")来看看各自的运行时间。

    这里我随机生成10000个1到100000的数,随机生成函数代码贴出来,具体就不做解释了

    function random(rangeL, rangeR, n){//[rangeL,rangeR]范围,总共有n个数
        let arr = [];
        for( let i = 0; i < n; i++ ){
            let num = parseInt(Math.random()*(rangeR-rangeL+1)+rangeL,10);
            arr.push(num);
        }
    
        return arr;
        
    }

    然后使用console.time("xxx")和console.timeEnd("xxx")来包裹我的循环,在Chrome测试出了两个算法各自运行时间

    selectsort: 141.809ms
    InsertSort: 70.291ms

    得出插入排序算法比选择排序算法更快。

    但是好好想想插入排序算法是否可以进行优化,因为不停地交换位置非常的耗时间,我们可以把手中的牌拿出来,先作对比,然后找到合适的位置再放进去,这样不就节省了很多时间吗?

    我们回到这个数组:[1,7,4,2,5,9]

    1、我们手中第一个牌是1,摸第二张牌7,和1比较不用交换。

    2、接下来摸第三张牌4,单独用一个变量存储4,然后和7比较,发现需要放到7的前面,这个时候我们要做的是把7复制到4的位置。然后和1比较,发现不用交换了,这个时候让前面放置4的变量放到7的位置上,这个时候数组变成了[1,4,7,2,5,9]。

    3、接下来第四张牌2,和7做对比需要交换,这个时候把7复制到2的位置[1,4,7,7,5,9],然后和4做对比也需要交换位置,把4复制到7的位置[1,4,4,7,5,9],然后再和1比较不需要交换位置,最后把存储2的变量放到4的位置[1,2,4,7,5,9]。

    以此类推,不断的挪动位置,给手中的牌腾出空间。这样我们就不用总是交换了,节省了很大的时间,代码实现如下(可以用while,也可以用for):

    for(let i = 1; i <arry.length; i++){
        let num = arry[i];//标记摸到的牌到变量
        let j = i - 1;//初始化手中的牌
        
        for(; j >= 0 && arry[j] > num; j--){//进行比较并且复制                
            arry[j+1] = arry[j];
        }
    
                  //找到合适的位置然后赋值   
             arry[j+1] = num;
    }

    我们再来测试一下这个插入排序算法和选择排序算法的性能

    selectsort: 124.689ms
    insertsort1: 44.823ms

    我们可以看到插入排序算法又快了很多。

    若是数组顺序不乱,那么插入排序会更加的快!!因为插入排序遇到了合适的位置就不遍历了,但是选择排序会遍历到底,找到最小数。

    所以在性能上来说,插入排序是优于选择排序的~!

    今天就是我学习的算法基础,明天若有新的进度继续更新

  • 相关阅读:
    Arduino-LCD1602液晶显示器
    photoshop--选区变形
    利用github给国外文件下载加速
    开发老人笔记:Git 常用命令清单
    区块链轻节点:“身”轻,责任重
    需求条目化:一个让用户故事有效落地的套路
    十八般武艺玩转GaussDB(DWS)性能调优:Plan hint运用
    跨越全场景统一架构三大挑战,MindSpore亮出“四招”
    看图学NumPy:掌握n维数组基础知识点,看这一篇就够了
    进来抄作业:分布式系统中保证高可用性的常用经验
  • 原文地址:https://www.cnblogs.com/claireyu1219/p/6607635.html
Copyright © 2011-2022 走看看