返回

JavaScript算法大揭秘:排序篇

前端

前言

算法是计算机科学的核心,排序算法是其中最基础也是最重要的算法之一。排序算法的作用是将一组数据按照某种顺序排列,以便于查找、比较和分析。在JavaScript中,有许多不同的排序算法,每种算法都有其独特的优缺点。

冒泡排序

冒泡排序是一种简单的排序算法,它通过一遍一遍地比较相邻的元素,将较大的元素“冒泡”到数组的末尾。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1)。

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

  return array;
}

选择排序

选择排序是一种比冒泡排序更有效的排序算法,它通过在数组中找到最小元素,然后将其与第一个元素交换,以此类推,直到将所有元素排序完毕。选择排序的时间复杂度为O(n^2),空间复杂度为O(1)。

function selectionSort(array) {
  for (let i = 0; i < array.length - 1; i++) {
    let minIndex = i;
    for (let j = i + 1; j < array.length; j++) {
      if (array[j] < array[minIndex]) {
        minIndex = j;
      }
    }

    let temp = array[i];
    array[i] = array[minIndex];
    array[minIndex] = temp;
  }

  return array;
}

插入排序

插入排序是一种比冒泡排序和选择排序更有效的排序算法,它通过将每个元素插入到已排序的子数组中来实现排序。插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。

function insertionSort(array) {
  for (let i = 1; i < array.length; i++) {
    let key = array[i];
    let j = i - 1;
    while (j >= 0 && array[j] > key) {
      array[j + 1] = array[j];
      j--;
    }

    array[j + 1] = key;
  }

  return array;
}

归并排序

归并排序是一种分治算法,它将数组分成更小的子数组,对每个子数组进行排序,然后合并这些排序好的子数组。归并排序的时间复杂度为O(n log n),空间复杂度为O(n)。

function mergeSort(array) {
  if (array.length <= 1) {
    return array;
  }

  let mid = Math.floor(array.length / 2);
  let leftHalf = mergeSort(array.slice(0, mid));
  let rightHalf = mergeSort(array.slice(mid));

  return merge(leftHalf, rightHalf);
}

function merge(left, right) {
  let merged = [];
  let leftIndex = 0;
  let rightIndex = 0;

  while (leftIndex < left.length && rightIndex < right.length) {
    if (left[leftIndex] < right[rightIndex]) {
      merged.push(left[leftIndex]);
      leftIndex++;
    } else {
      merged.push(right[rightIndex]);
      rightIndex++;
    }
  }

  while (leftIndex < left.length) {
    merged.push(left[leftIndex]);
    leftIndex++;
  }

  while (rightIndex < right.length) {
    merged.push(right[rightIndex]);
    rightIndex++;
  }

  return merged;
}

快速排序

快速排序是一种分治算法,它通过选择一个枢轴元素,将数组分成两个子数组,然后对这两个子数组进行排序,再合并这些排序好的子数组。快速排序的时间复杂度为O(n log n),空间复杂度为O(log n)。

function quickSort(array) {
  if (array.length <= 1) {
    return array;
  }

  let pivot = array[0];
  let left = [];
  let right = [];

  for (let i = 1; i < array.length; i++) {
    if (array[i] < pivot) {
      left.push(array[i]);
    } else {
      right.push(array[i]);
    }
  }

  return [...quickSort(left), pivot, ...quickSort(right)];
}

堆排序

堆排序是一种基于堆数据结构的排序算法,它通过构建一个最大堆,然后依次从堆中取出最大元素,直到堆为空。堆排序的时间复杂度为O(n log n),空间复杂度为O(1)。

function heapSort(array) {
  let heapSize = array.length;

  buildMaxHeap(array);

  for (let i = array.length - 1; i > 0; i--) {
    let temp = array[0];
    array[0] = array[i];
    array[i] = temp;

    heapSize--;
    maxHeapify(array, 0, heapSize);
  }

  return array;
}

function buildMaxHeap(array) {
  for (let i = Math.floor(array.length / 2) - 1; i >= 0; i--) {
    maxHeapify(array, i, array.length);
  }
}

function maxHeapify(array, i, heapSize) {
  let largest = i;
  let left = 2 * i + 1;
  let right = 2 * i + 2;

  if (left < heapSize && array[left] > array[largest]) {
    largest = left;
  }

  if (right < heapSize && array[right] > array[largest]) {
    largest = right;
  }

  if (largest !== i) {
    let temp = array[i];
    array[i] = array[largest];
    array[largest] = temp;

    maxHeapify(array, largest, heapSize);
  }
}

计数排序

计数排序是一种非比较排序算法,它通过统计每个元素出现的次数,然后根据这些次数将元素排序。计数排序的时间复杂度为O(n + k),空间复杂度为O(k),其中k是数组中元素的最大值。

function countingSort(array) {
  let max = Math.max(...array);
  let counts = new Array(max + 1).fill(0);

  for (let i = 0; i < array.length; i++) {
    counts[array[i]]++;
  }

  let sortedArray = [];
  let currentCount = 0;

  for (let i = 0; i <= max; i++) {
    while (counts[i] > 0) {
      sortedArray.push(i);
      counts[i]--;
      currentCount++;
    }
  }

  return sortedArray;
}

桶排序

桶排序是一种非比较排序算法,它通过将数组分成若干个桶,然后将每个元素放入相应的桶中,再对每个桶中的元素进行排序,最后将所有桶中的元素合并。桶排序的时间复杂度为O(n + k),空间复杂度为O(n + k),其中k是桶的数量。

function bucketSort(array) {
  let minValue = Math.min(...array);
  let maxValue = Math.max(...array);
  let bucketSize = Math.floor((maxValue - minValue) / k);

  let buckets = [];
  for