JS中算法之排序算法

1、基本排序算法

1.1、冒泡排序

它是最慢的排序算法之一。

1、不断比较相邻的两个元素,如果前一个比后一个大,则交换位置。

2、当比较完第一轮的时候最后一个元素应该是最大的一个。

3、按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以第二轮的时候最后一个元素不用比较,此后依次类推。

                      冒泡排序动图演示:

冒泡排序

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

另一种写法可能更好理解:每一次比较后都拿最小的那个元素放到前面

for (let i = 0; i < ns.length - 1; i++) {
    for (let j = i + 1; j < ns.length; j++) {
        let temp;
        if (ns[i] > ns[j]) {
            temp = ns[i];
            ns[i] = ns[j];
            ns[j] = temp;
        }
    }
}

1.2、选择排序

从数组的开头开始,将第一个元素和其他元素进行比较,比较完所有元素后,将最小的元素与第一个元素交换,然后算法会从第二个元素继续,依次类推。当进行到数组的倒数第二个位置时,所有的数据便完成了排序。

                      选择排序动图演示:

选择排序动图

function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     //寻找最小的数
                minIndex = j;                 //将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}

 1.3、插入排序

从第二个元素开始循环,当前面的元素比选中的元素大时将前面的元素向右移动,直至比较到第1个元素(即索引为0)或者前面的元素不再比选中的大,此时将选中的元素赋值给比它小的元素之后的位置。

                      插入排序动图演示:

插入排序动图

function insertionSort(arr) {
    var len = arr.length;
    var preIndex, current;
    for (var i = 1; i < len; i++) {
        preIndex = i - 1;
        current = arr[i];  //此时选中的元素
        while(preIndex >= 0 && arr[preIndex] > current) {
            arr[preIndex+1] = arr[preIndex];  //当比选中的元素大时元素向右移
            preIndex--;
        }
        arr[preIndex+1] = current;  //将选中的元素赋值给比它小的元素之后的位置
    }
    return arr;
}

以上的三种基本排序算法中,选择排序和插入排序要比冒泡排序快,插入排序是这三种算法中最快的

2、高级排序算法

高级排序算法被认为是处理大型数据集的最高效排序算法,它们处理的数据集可以达到上百万个元素。

2.1、希尔排序

这在插入排序的基础上做了很大的改善。它会首先比较距离较远的元素,而非相邻的元素。比较的元素之间的距离会不断减小,直至比较的是相邻元素,此时就是一个直接的插入排序。在开始做最后一次处理时,大部分元素都已经在正确的位置,算法就不必对很多元素进行交换,这就是希尔排序比插入排序更高效的地方。

比如:数组为 [49,38,65,97,26,13,27,49,55,4],当间隔为5时,将分组为五组数据(49,13)、(38,27)、(65,49)、(97,55)、(26,4),分别对五组数据进行直接的插入排序,然后此时的数组会变为 [13,27,49,55,4,49,38,65,97,26],依次类推直至间隔为1

通过定义一个间隔序列来表示在排序过程中进行比较的元素之间有多远的间隔。下面的算法时是动态定义间隔序列。

function shellSort(arr) {
  var len = arr.length, current, gap = 1;
  while (gap < len / 3) {          //动态定义间隔序列
    gap = gap * 3 + 1;
  }
  for (gap; gap > 0; gap = Math.floor(gap / 3)) {  //间隔在不断改变,直至为 1
    for (var i = gap; i < len; i++) {   //从数组索引为间隔大小的位置开始
      current= arr[i];  //相当于直接插入排序的选中元素
      for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {  //间隔序列所间隔开的元素进行直接插入排序
        arr[j + gap] = arr[j];
      }
      arr[j + gap] = current;  //将选中的元素赋值给比它小的元素之后的位置
    }
  }
  return arr;
}

2.2、归并排序

归并排序的实现有两种方法:1、自上而下(自顶向下)的递归  。2、自下而上(自底向上)的迭代

将数据集分解为多组分别只有一个元素的数组,然后通过创建一组左右子数组将它们两两有序地合并起来,直到最后合并剩下的两个大的数组组成有序的完整数组。

                        归并排序动图演示:

归并排序动图

function mergeSort(arr) { 
  var len = arr.length;
  if (len < 2) {
    return arr;
  }
  var middle = Math.floor(len / 2),
    left = arr.slice(0, middle),
    right = arr.slice(middle);
  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
  var result = [];

  while (left.length && right.length) {
    if (left[0] <= right[0]) {
      result.push(left.shift());
    } else {
      result.push(right.shift());
    }
  }

  while (left.length)
    result.push(left.shift());

  while (right.length)
    result.push(right.shift());

  return result;
}

2.3、快速排序

是处理大数据最快的排序算法之一,快速排序算法非常适用于大型数据集合;在处理小数据集时性能反而会下降。

(1) 选择一个基准元素,将列表分隔成两个子序列,将所有小于基准值的元素放在基准值的前面,所有大于基准值的元素放在基准值的后面; (2) 分别对较小元素的子序列和较大元素的子序列重复步骤 1

                        快速排序动图演示:

快速排序动图

function qSort(arr) {
  if (arr.length == 0) {
    return [];
  }
  var left = [];
  var right = [];
  var pivot = arr[0];
  for (var i = 1; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return qSort(left).concat(pivot, qSort(right));  //小的元素都放在了基准值的左边,大的都放在了右边。小的和大的分别进行了递归,结果也是如此,所以完成了排序。
}

 3、时间、空间复杂度

原文地址:https://www.cnblogs.com/wenxuehai/p/10306816.html