几种 JavaScript 排序方法

64 阅读2分钟

1、冒泡排序

冒泡排序就是重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”这一操作的算法。在这个过程中,数字会像泡泡一样,慢慢“浮”到序列的顶端(或底端),所以这个算法才被称为“冒泡排序”。

const bubbleSort = (arr) => {
  const len = arr.length;
  for (let i = 0; i < len; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
};
// 时间复杂度为 O(n^2)。

2、选择排序

选择排序就是重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”这一操作的算法。在序列中寻找最小值时使用的是线性查找。

const selectSort = (arr) => {
  const len = arr.length;
  let minIndex;
  for (let i = 0; i < len - 1; i++) {
    minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
  }
  return arr;
};
// 时间复杂度为 O(n^2)。

3、插入排序

插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程中,左侧的数据陆续归位,而右侧留下的就是还未被排序的数据。插入排序的思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。

const insertSort = (arr) => {
  const len = arr.length;
  let preIndex, curr;
  for (let i = 1; i < len; i++) {
    preIndex = i - 1;
    // 存储当前i的值,后面换位使用
    curr = arr[i];
    // 当前i值与左侧数据(已排序)比较,直到找到左侧数据(已排序)的元素小于或者等于当前i值的位置
    while (preIndex >= 0 && arr[preIndex] > curr) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = curr;
  }
  return arr;
};
// 时间复杂度为 O(n^2)。

4、快速排序

快速排序算法首先会在序列中随机选择一个基准值(pivot),然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成以下形式。

[ 比基准值小的数 ] 基准值 [ 比基准值大的数 ]

接着,对两个“[ ]”中的数据进行排序之后,整体的排序便完成了。对“[ ]”里面的数据进行排序时同样也会使用快速排序。

const quickSort = (arr) => {
  const len = arr.length;
  if (len <= 1) {
    return arr;
  }
  const pivotIndex = Math.floor(len / 2);
  const pivot = arr.splice(pivotIndex, 1)[0];
  const left = [],
    right = [];
  // splice 使 arr减少一位,故 len - 1
  for (let i = 0; i < len - 1; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }

  return quickSort(left).concat([pivot], quickSort(right));
};
// 时间复杂度为 OO(nlogn)。

灵感来自《我的第一本算法书》