• JavaScript实现各种排序算法


    前言:本文主要是用JavaScript实现数据结构中的各种排序算法,例如:插入排序
    、希尔排序、合并排序等。

    冒泡排序


    function bubbleSort(arr) {
           console.time("冒泡排序")var num = 0;
                for (var i = arr.length; i > num; num++) {
                    for (var j = i - 1; j > num; j--) {
                        if(arr[j-1]>arr[j]){
                        var temp = arr[j-1];
                        arr[j-1] = arr[j];
                        arr[j] = temp;
                      }
                    }
                }
            console.timeEnd("冒泡排序")
            return arr
       }
       var arr = [12, 290, 219, 278, 4432,21, 43, 89, 78];
       console.log( bubbleSort(arr));

     

    时间复杂度: 最差 O(n2) ; 最优 O(n)

    插入排序


     插入排序的基本原理如下图:从前向后构建有序序列,对于未排序序列,在已排序的序列中从后向前扫描插入位置,对于第p个元素,需要扫描p-1次,平均来说插入排序算法复杂度为O(n2)

    function insertSort(arr) {
        console.time("插入排序")
    
        var len = arr.length;
    
        if (len <= 1) {
            return arr;
        }
    
        // 1~n-1趟排序
        arr.map(function(item,index){
          if(index>0){
            for (var j = index; j > 0 && arr[j - 1] > item; j--) {
                arr[j] = arr[j - 1];
            }
            arr[j] = item;
          }
      });
        console.timeEnd("插入排序")
        return arr
    }
    var arr = [12, 290, 219, 278, 4432, 21, 43, 89, 78];
    console.log(insertSort(arr));

    希尔排序


     shell排序也称为递减增量排序,效果比插入排序更好,对于不同的增量,排序性能也不同

    下面我们看看 步长选择为frac{n}{2}并且对步长取半直到步长达到1的算法实现。

    function shellSort(arr) {
        console.time("希尔排序")
        var gap, i, j;
        var temp;
        for (gap = arr.length >> 1; gap > 0; gap >>= 1)
            for (i = gap; i < arr.length; i++) {
                temp = arr[i];
                for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
                    arr[j + gap] = arr[j];
                arr[j + gap] = temp;
            }
        console.timeEnd("希尔排序")
        return arr
    }
    var arr = [12, 290, 219, 278, 4432, 21, 43, 89, 78];
    console.log(shellSort(arr));

    算法实现过程如下:这里我们选择 步长为4:(每一列相当于一次插入排序

    12        190  219  278
    4432    21    43    89
    78
    // 第一次排序之后得到:
    12      21     43      89
    78      190   219    278
    4432
    
    // 连接起来得到的是 [12,21,43,89,78,190,219,278,4432],接着以2为步长 排序之后变为:
    12    21
    43    89
    78    190
    219  278
    4432
    
    // 然后就是简单的插入排序

    平均时间复杂度为: O(nlog^2 n)

    快速排序


      快排的思想也很简单,以升序为例,在序列中选一标杆,一般讲第一个元素作为标杆,然后将序列中比标杆小的元素放到标杆左边,将比标杆大的放到标杆右边。然后分别在左右两边重复这样的操作。

      快速排序的关键在于选取中心枢纽povit,该值可以随机选择,但是不同的选择会有所影响,在这里我直接选择了最左端的元素

    void ksort(int a[], int l, int r) {
        // 长度小于2有序
        if (r - l < 2) return;
        int start = l, end = r;
        while (l < r) {
            // 向右去找到第一个比标杆大的数
            while (++l < end && a[l] <= a[start]);
            // 向左去找第一个比标杆小的数9 while(--r > start && a[r] >= a[start]);
            if (l < r) swap(a[l], a[r]); // 前面找到的两个数相对于标杆逆序 ,需交换过来 。l==r 不需要交换,
        }
        swap(a[start], a[r]); // 将标杆挪到正确的位置.
        // 对标杆左右两边重复算法,注意,这个l已经跑到r后面去了
        ksort(a, start, r);
        ksort(a, l, end);
    }

     快速排序实现2: (以中间的为基准值)

     1 function qSort(arr) {
     2   if (arr.length <= 1) {
     3     return arr;
     4   }
     5   var num = Math.floor(arr.length / 2);
     6 
     7   var numValue = arr.splice(num, 1)[0];
     8   var left = [],
     9     right = [];
    10   for (var i = 0; i < arr.length; i++) {
    11     if (arr[i] < numValue) {
    12       left.push(arr[i]);
    13     } else {
    14       right.push(arr[i]);
    15     }
    16   }
    17   return qSort(left)
    18     .concat([numValue], qSort(right))
    19 }
    20 
    21 console.log(qSort([32, 45, 37, 16, 2, 87]))

    快速排序的平均时间复杂度为O(NLogN)

    合并排序

     合并排序采用分治法的思想对数组进行分治,对半分开,分别对左右两边进行排序,然后将排序后的结果进行合并。按照这样的思想,递归做是最方便的。

     1 int a[N], c[N];
     2 void mergeSort(l, r) {
     3   int mid, i, j, tmp;
     4   if (r - 1 > l) {
     5     mid = (l + r) >> 1;
     6     // 分别最左右两天排序
     7     mergeSort(l, mid);
     8     mergeSort(mid, r);
     9     // 合并排序后的数组
    10     tmp = l;
    11     for (i = l, j = mid; i < mid && j < r;) {
    12       if (a[i] > a[j]) c[tmp++] = a[j++];
    13       else c[tmp++] = a[i++];
    14     }
    15     // 把剩余的接上
    16     if (j < r) {
    17       for (; j < r; j++) c[tmp++] = a[j];
    18     } else {
    19       for (; i < mid; i++) c[tmp++] = a[i];
    20     }
    21     // 将c数组覆盖到a里
    22     for (i = l; i < r; i++) {
    23       a[i] = c[i];
    24     }
    25   }
    26 }

     

    结束语

      更新几种排序算法的实现

  • 相关阅读:
    Vue--会员管理列表页面,抽取BASE_URL
    Vue--系统权限拦截
    写译-冲刺班
    看到一篇有收获的博文【关于外挂生涯的忠告】(转载)
    笔记管理-vscode-印象笔记-git-博客园
    1.4条件和循环
    1.3撰写表达式
    1.2对象定义与初始化
    1.1如何写一个c++程序
    send()函数 recv()函数
  • 原文地址:https://www.cnblogs.com/kasmine/p/6416472.html
Copyright © 2020-2023  润新知