常见算法之排序算法

113 阅读1分钟

冒泡排序:

时间:最好 O(n), 平均 O(n^2), 最差 O(n^2)

空间:O(1)

function bubbleSort(arr) {
  // n 个数字需要最多需要遍历 n - 1 轮
  for (let i = 0; i < arr.length - 1; i++) {
    // swapped 优化遍历轮数,一轮中没有交换元素说明排序已完成
    let swapped = false;
    // 优化比较次数:每一轮至少一个元素冒泡到最后,该元素下一轮无需比较,所以每轮比较 n - 1 - i 次
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        swap(arr, j, j + 1);
        swapped = true;
      }
    }
    if (swapped === false) {
      break;
    }
  }
  return arr;
}
function swap(arr, i, j) {
  let temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

插入排序

时间:最好 O(n), 平均 O(n^2), 最差 O(n^2)

空间: O(1)

function insertionSort(arr) {
  if (!arr || arr.length < 2) return arr;
  // 默认第一个元素已排好序,从第二个元素开始遍历
  for (let i = 1; i < arr.length; i++) {
    // 把当前元素插入到该元素左边已排好序的数组里
    // arr[i] = valueToInsert
    for (let j = i - 1; j >= 0; j--) {
      if (arr[j] > arr[j + 1]) {
        swap(arr, j, j + 1);
      } else {
        break;
      }
    }
  }
  return arr;
}

选择排序

时间:最好 O(n^2), 平均 O(n^2), 最差 O(n^2)

空间:O(1)

function selectionSort(arr) {
  if (!arr || arr.length < 2) return arr;
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[i]) {
        swap(arr, i, j);
      }
    }
  }
  return arr;
}

并归排序

时间:最好 O(n log(n)), 平均 O(n log(n)), 最差 O(n log(n))

空间:O(n)

function mergeSort(arr, start, end) {
  if (!arr || arr.length < 2) return arr;
  if (start >= end) return;
  const mid = Math.floor((start + end) / 2);
  
  mergeSort(arr, start, mid);
  mergeSort(arr, mid + 1, end);
  merge(arr, start, mid, end);
  return arr;
}

function merge(arr, start, mid, end) {
  let result = [];
  let i = 0;
  let p1 = start;
  let p2 = mid + 1;

  while (p1 <= mid && p2 <= end) {
    if (arr[p1] < arr[p2]) {
      result[i++] = arr[p1++];
    } else {
      result[i++] = arr[p2++];
    }
  }
  while (p1 <= mid) {
    result[i++] = arr[p1++];
  }
  while (p2 <= end) {
    result[i++] = arr[p2++];
  }
  for (i = 0; i < result.length; i++) {
    arr[start + i] = result[i];
  }
}

快速排序

时间:最好 O(n log(n)), 平均 O(n log(n)), 最差 O(n^2)

空间:O(log(n))

function quickSort(arr, left, right) {
  if (!arr || arr.length < 2) return arr;
  if (left < right) {
    let pi = partition(arr, left, right);
    quickSort(arr, left, pi - 1);
    quickSort(arr, pi + 1, right);
  }
  return arr;
}

function partition(arr, left, right) {
  let pivot = arr[right];
  // i keeps track of value smaller than pivot
  let i = left - 1;
  for (let j = left; j < right; j++) {
    if (arr[j] < pivot) {
      // makes all numbers right to i are smaller than pivot
      i++;
      // swap i with latest small value
      swap(arr, i, j);
    }
  }
  // swap i + 1 with pivot
  swap(arr, i + 1, right);
  return i + 1;
}