zoukankan      html  css  js  c++  java
  • js数组排序方法总结

    前言

    这是第一次开通博客,写一些关于关于前端的知识总结,方便他人也方便自己忘的时候翻出来看看,希望自己可以一直坚持下去,如果文中有哪些不对的、需要改进的,欢迎大家批评指正

    正文

    一、冒泡排序

    冒泡排序初级:

    冒泡就是通过数组中相邻的两项进行比较,然后把数值大的项放到后面,从图示中可以看出从第一项开始比较一共比较了四次,也就是数组长度length-1,对应到代码就是解决两个问题:1.如何交换两个数组的值。2.确定for循环的次数。第一个问题我们通过设置一个中间媒介接收较大的值,第二个问题刚才已经讨论过了,就是数组长度的length-1,所以对应的代码如下:

    // 设置一个中间值来保存较大的项的值
    var medium = null;
            for (var i = 0; i <= arr.length-1; i++) {
                if (arr[i] > arr[i+1]) {
                    medium = arr[i];
                    arr[i] = arr[i+1];
                    arr[i+1] = medium;
                }
            }
    

    但这只是从数组的第一项开始比较了一遍,后面还要从数组的第二项往后比较,然后是第三项,第四项,第五项就不需要在比较了,因为他是数组从第一项开始比较后的结果,已经是数组的最大值,所以这个循环还需要再嵌套一个循环中,循环次数即为数组长度的length-1对应的代码如下:

    var medium = null;
            for (var j = 0; j <= arr.length-1; j++) {
                for (var i = 0; i <= arr.length-1; i++) {
                if (arr[i] > arr[i+1]) {
                    medium = arr[i];
                    arr[i] = arr[i+1];
                    arr[i+1] = medium;
                }
            }
            }
    

    冒泡排序中级:

    我们在对这个排序方法进行优化,看下面的图解:

    这次比较中是从数组的第二项开始比较(第一项经过比较已经成为最后一项),这次比较的次数是3,对应的最外层循环是 j=1 ,再看下面,

    这次比较是从数组的第三项开始比较,这次的比较次数是2,对应的外层循环是 j=2 ,所以不难发现内层循环对应的比较次数是 arr.length-1-j ,所以优化后代码如下:

    var medium = null;
            for (var j = 0; j <= arr.length-1; j++) {
                for (var i = 0; i <= arr.length-1-j; i++) {
                if (arr[i] > arr[i+1]) {
                    medium = arr[i];
                    arr[i] = arr[i+1];
                    arr[i+1] = medium;
                }
            }
            }
    

    冒泡排序高级版:

    如果理解了上述两个方法,我们再来介绍一下终极版的冒泡排序,下面看一个数组的极端例子:

    这已经是一个冒泡好的数组,在我们从人的思维来看,这个数组根本不需要排序,但计算机并不知道这个数组已经排好序了,在进行了内层循环的第一次后,我们是否可以给计算机一个判断条件让他去判断是否还要去进行外部的循环,所以我们做出一个假设,假设这个数组已经排好序了,然后我们让计算机去检测这个假设成不成立,如果数组排好序,那么必然有 arr[i+1]>arr[i] ,如果我们将数组遍历一遍找不到推翻这个条件的例子,那么就可以立即结束外层循环,不必在进行下去,那么我们来看代码如何实现:

    var medium = null; 
            for (var j = 0; j <= arr.length-1; j++) {
                var flag = true;
                for (var i = 0; i <= arr.length-1-j; i++) {
                if (arr[i] > arr[i+1]) {
                    medium = arr[i];
                    arr[i] = arr[i+1];
                    arr[i+1] = medium;
                    flag = false
                }
            }
            if (flag) {
                break
            }
            }
    

    二、快速排序

    快速排序就是在数组中挑出中间项,然后定义两个空数组,让需要比较的数组里的项分别与这个中间项进行比较。把小于这个中间项的放到一个空数组里面,把大于这个中间项的放到一个空数组里面,然后使用递归重复这个过程。下面看代码的实现:

    function quick(arr) {
                if (arr.length<=1){return arr}
                // 取数组的中间项的下标
                var middleIndex = Math.floor(arr.length / 2);
                // 取出数组的中间项,并把该项从数组中删除,且原数组受到影响
                var middle = arr.splice(middleIndex,1)[0];
                // 声明两个数组,分别用来存在比middle小和大的值
                var leftArr = [];
                var rightArr = [];
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i] <= middle) {
                        leftArr.push(arr[i])
                    } else if (arr[i] > middle) {
                        rightArr.push(arr[i])
                    }
                }
                // 使用递归,并把三个数组拼接起来
                return quick(leftArr).concat([middle],quick(rightArr))
            }
    

    三、插值排序

    插值排序,我个人感觉有些抽象,对象到现实中可以理解成打扑克牌,我们左手拿着已经排好的牌,右手去摸排,摸到的牌插到左手里面已经排好的牌,这次我们先上代码,然后我们在对应着代码按我理解的去解释,代码如下:

    function insertSort(arr) {
                //从第二个数开始,依次插入
                for (var i = 1; i < arr.length; i++) {
                    //判断目标元素是否小于前一个元素
                    if (arr[i] < arr[i - 1]) {
                        var current = arr[i];
                        var j = i - 1;
                        //从有序数列从后往前对比,如果目标元素小于与之对比的当前元素,当前元素位置往后挪一位
                        while (j >= 0 && current < arr[j]) {
                            arr[j + 1] = arr[j];
                            j--;
                        }
                        //插入
                        arr[j + 1] = current;
                    }
                }
                return arr;
            }
    

    首先是一个for循环,这一步的目的其实就是让数组整体从前往后开始比较,先看看数组的前面几项是不是是一个有序数组(就是你左手中的牌),在循环中我们突然找到了一项,发现他比前一项要小,我们为了方便就管这一项取名为small,试想如果small加上前面的有序数组是不是就组成了一个无序数组,所以我们就要想办法把这个small插入到这个有序数组里,让small在合适的位置与这个有序数组再次组成一个新的有序数组,那么这里就是对应到if()判断语句成立的条件,好的进入if循环,我们用一个变量也就是代码中的current去保存small的值,在用一个变量也就是j记录下来small前一项对应的下标,那我们就拿着这个current去和有序数组里面的每一个值去比较而且是从后往前比较,这里对应上了while循环体,只要有序数组里的项比大他就让这一项往后一移一位,即

    arr[j + 1] = arr[j];
    

    但也可以理解为没有后移,只不过是让后面一项等于了自己,然后我们还要继续从后往前比,所以 j-- ,直到出现small的值也就是current大于有序数组里的一项时。我们终于找到了small要插入的位置,跳出while循环体,把small插到这一项的后面也就是 arr[j + 1] = current ,然后继续进行for循环,重复这个过程。

  • 相关阅读:
    Android_AyscnTask
    Android_handler
    Android_网络操作
    Android_网络基础
    Android_Fragment
    Android_activity 生命周期
    Android-Dialog
    android_menu
    Android-约束布局
    andorid_相对布局小练习
  • 原文地址:https://www.cnblogs.com/jojo-star/p/13396130.html
Copyright © 2011-2022 走看看