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(n\log^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 }

 

 

 

结束语

  更新几种排序算法的实现

posted @ 2017-02-24 22:26  Kasmine  阅读(277)  评论(0编辑  收藏  举报