前端开发需要理解的排序算法

如何理解JavaScript中常用的4种排序算法

前端 排序算法总结

javascript自带排序算法

一、Array.prototype.sort

  1. 时间复杂度:快速排序(O(nlogn))

注意,从 javascript 源码的角度来看,在实现上明显比一般使用的快速排序复杂,其主要是做了性能上的优化。因此, sort 函数在性能上是无法被质疑的。

  1. 优势

除了性能上,sort 还是一个高阶函数,可以接受一个函数作为参数。sort 默认会将元素类型转化成字符串进行排序,但通过传入的函数参数,可以调整数组的升序或者降序。

  1. 代码

    arr.sort((item1, item2) => item1 - item2) /从小到大排序,sort的函数参数返回值若为负值,不作swap,若为正值,swap/

其他

一、插入排序

  1. 时间复杂度:O(n^2)。

插入排序在实践中的使用频率很高,在一些场景下,甚至展现出完胜高级排序的效率,如每次动态生成一个元素,并将其插入某个数组,假如有排序的需求,此时插入排序就能派上用场了,所以首先解释插入排序。

  1. 算法介绍(从小到大):
  • 从第一个默认被排好序的元素开始
  • 取下一个元素,在已经排序的元素数组(从小到大)中由后向前扫描
  • 当往前扫描到比之大的,将其后移一位
  • 重复第三步骤
  • 直到扫描到比之小的,插入其后
  1. 理解:

插入排序的思路跟整理扑克牌是一样的,即每次拿到一张牌,按大小顺序将其插入到合适的位置,即每次将一个数插入到有序的数组中去。

  1. 优势:

插入排序的精髓在于,如果对一个已经有序的数组扫描插入目标位置,最终只会遍历数组一遍,这样时间复杂度退化为O(n)。另外,如果对一个接近有序的数组使用插入排序,其效率是非常可观的。而在很多场景,我们处理的数据是接近有序的,只需调整一些无序项

  1. 代码:

    function insertion_sort(arr) {
    for(var i=1;i<arr.length;i++) {
    var temp = arr[i];
    var j = i-1;
    while(arr[j] > temp) { /找到比之大的,将其后移一位/
    arr[j+1] = arr[j];
    j–;
    }
    arr[j+1] = temp; /找到比之小的,插入其后/
    }
    return arr;
    }

二、二分法插入排序

  1. 时间复杂度

是插入排序的改进。每次二分,可以不用由后往前一个个遍历。

  1. 算法介绍

  2. 代码

    function insertion_sort_binary(arr) {
    for(var i = 1; i<arr.length;i++) {
    var temp = arr[i];
    var left = 0, right = i-1;

         while(left < = right) {
             var middle = parseInt((left+right)/2);
             
             if(temp < arr[middle]) right = middle-1;
             else left = middle+1;
         }
         
         for(var j=i-1;j>=left;j--) {
             arr[j+1] = arr[j]; /*找到比之大的,将其后移一位*/
         }
         
         arr[left] = temp; /*找到比之小的,插入其后*/
         
     }
     
     return arr;
    

    }

三、冒泡排序

  1. 时间复杂度:O(n^2)

  2. 算法介绍

  • 每轮由前往后比较相邻的两个元素,如果前一个比后一个大,则交换位置。如1和2,2和3…
  • 第一轮把最大的元素放到了最后面
  • 由于每轮排序结束后最后一个都是最大的,所以之后按照步骤1排序最后一个元素不用比较
  1. 优势

需要被优化,一般不会使用。可以使用快速排序带标志位的冒泡排序

  1. 代码

四、带标志位(true/false)的冒泡排序

  1. 时间复杂度:O(n)
  2. 算法介绍
  • 每轮由前往后比较相邻的两个元素,如果前一个比后一个大,则交换位置。如1和2,2和3…
  • 第一轮把最大的元素放到了最后面
  • 由于每轮排序结束后最后一个都是最大的,所以之后按照步骤1排序最后一个元素不用比较
  • 如果某一轮没有发生swap,标志设置为false,将不进行循环遍历,表示排序已经完成
  1. 代码

    function bubble_sort_flag(arr){
    var flag = true;
    var swap;

     while(flag) {
         flag = false;
         
         for(var j = 1;j<n;j++) {
             if(arr[j-1]>arr[j]) {
                 swap = arr[j-1];
                 arr[j] = swap;
                 arr[j] = swap;
                 
                 flag = true; /*每轮发生swap就将flag设置为true*/
             }
         }
         n--;
     }
     return arr;
    

    }

五、记录最后一次交换的位置的冒泡排序

  1. 时间复杂度:O(n)

  2. 算法介绍

  3. 代码

六、快速排序(归并排序、堆排序、希尔排序)

  1. 时间复杂度:O(nlogn)

快速排序是对冒泡排序的一种改进。

  1. 算法介绍
  • 首先找到一个基数,pivot,一般选择最后一个元素或中间位置元素
  • 将pivot和Math.floor(arr.length/2)位置进行swap
  • 将比pivot小的值放在其左边
  • 将比pivot大的值放在右边
  • 递归分好的两个组执行快排
  1. 代码

    function quick_sort(arr) {
    if(arr.length <= 1) {
    return arr;
    }

     var pivotIndex = Math.floor(arr.length/2);
     var pivot = arr.splice(pivotIndex, 1)[0];
     
     var left = [], right = [];
     
     for(var i=0;i<arr.length;i++) {
         if(arr[i] < pivot) left.push(arr[i]);
         else right.push(arr[i]);
     }
     
     /* 递归 */
     return quick_sort(left).concat([pivot], quick_sort(right))
    

    }

七、选择排序

  1. 时间复杂度:O(n^2)
  2. 算法介绍
  • 第一轮遍历从数组找出最小的,与第一个元素进行swap
  • 第二轮遍历从第二个元素开始,找出最小的,与第二个元素进行swap
  • 依次循环…
  1. 理解

这是一个不稳定的算法,因为每次交换都会改变后续数组的顺序。所以一般不会使用。

  1. 代码

猜你喜欢

转载自blog.csdn.net/hoanFir/article/details/89887883