返回

前端排序算法手册:用JavaScript实现十大经典算法

前端

作为前端开发人员,排序算法可能是我们经常忽略的一个方面。然而,掌握这些算法可以极大地提高我们的编码技能,并帮助我们解决各种复杂的问题。

本文将深入探讨十大经典排序算法,并使用JavaScript提供它们的实际实现。这些算法包括:

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 归并排序
  • 快速排序
  • 堆排序
  • 桶排序
  • 计数排序
  • 基数排序
  • 桶排序

我们将深入了解每种算法的工作原理、复杂度以及在不同情况下的适用性。同时,我们将通过实际代码示例来演示这些算法,以帮助您更好地理解它们的实现。

冒泡排序

冒泡排序是一种简单直观的排序算法,它通过反复比较相邻元素来排序数组。它将较大的元素“冒泡”到数组的末尾。

function bubbleSort(arr) {
  let swapped;
  do {
    swapped = false;
    for (let i = 0; i < arr.length - 1; i++) {
      if (arr[i] > arr[i + 1]) {
        let temp = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = temp;
        swapped = true;
      }
    }
  } while (swapped);
  return arr;
}

选择排序

选择排序是一种基于比较的算法,它通过在数组中找到最小元素并将其放置在适当的位置来进行排序。

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

插入排序

插入排序是一种高效的算法,特别适用于已经部分排序或几乎有序的数组。它通过将一个元素插入到前面已经排序的子数组中来进行排序。

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

归并排序

归并排序是一种稳定的排序算法,它使用分治策略对数组进行排序。它将数组分成较小的子数组,对它们进行排序,然后将它们合并回一个排序后的数组。

function mergeSort(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  let mid = Math.floor(arr.length / 2);
  let leftHalf = mergeSort(arr.slice(0, mid));
  let rightHalf = mergeSort(arr.slice(mid));
  return merge(leftHalf, rightHalf);
}

function merge(left, right) {
  let merged = [];
  while (left.length && right.length) {
    if (left[0] <= right[0]) {
      merged.push(left.shift());
    } else {
      merged.push(right.shift());
    }
  }
  return [...merged, ...left, ...right];
}

快速排序

快速排序是一种高效的排序算法,它使用分治策略对数组进行排序。它通过选择一个基准元素将数组分成较小的子数组,然后递归地对这些子数组进行排序。

function quickSort(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  let pivot = arr[arr.length - 1];
  let left = [];
  let right = [];
  for (let i = 0; i < arr.length - 1; i++) {
    if (arr[i] <= pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return [...quickSort(left), pivot, ...quickSort(right)];
}

堆排序

堆排序是一种基于比较的算法,它使用堆数据结构对数组进行排序。它通过将数组构建成一个堆,然后逐步弹出堆的根元素并将其放置在数组的末尾来进行排序。

function heapSort(arr) {
  // 建立最大堆
  for (let i = Math.floor(arr.length / 2) - 1; i >= 0; i--) {
    heapify(arr, arr.length, i);
  }

  // 排序
  for (let i = arr.length - 1; i >= 0; i--) {
    // 将根元素与最后一个元素交换
    let temp = arr[0];
    arr[0] = arr[i];
    arr[i] = temp;

    // 对剩余的数组重新建立堆
    heapify(arr, i, 0);
  }

  return arr;
}

function heapify(arr, n, i) {
  let largest = i;
  let left = 2 * i + 1;
  let right = 2 * i + 2;

  if (left < n && arr[left] > arr[largest]) {
    largest = left;
  }
  if (right < n && arr[right] > arr[largest]) {
    largest = right;
  }

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

    heapify(arr, n, largest);
  }
}

桶排序

桶排序是一种非基于比较的排序算法,它通过将数组元素分配到不同大小的桶中来进行排序。

function bucketSort(arr, n) {
  let buckets = [];
  for (let i = 0; i < n; i++) {
    buckets[i] = [];
  }

  // 将元素分配到桶中
  for (let i = 0; i < arr.length; i++) {
    let index = Math.floor(n * arr[i]);
    buckets[index].push(arr[i]);
  }

  // 对每个桶进行排序
  for (let i = 0; i < n; i++) {
    buckets[i] = insertionSort(buckets[i]);
  }

  // 将排序后的桶合并到一个数组中
  let sortedArr = [];
  for (let i = 0; i < n; i++) {
    sortedArr = [...sortedArr, ...buckets[i]];
  }

  return sortedArr;
}

计数排序

计数排序是一种非基于比较的排序算法,它适用于只包含有限数量不同元素的数组。

function countingSort(arr, max) {
  let counts = new Array(max + 1).fill(0);
  for (let i = 0; i < arr.length; i++) {
    counts[arr[i]]++;
  }

  // 累加计数
  for (let i = 1; i < counts.length; i++) {
    counts[i] += counts[i - 1];
  }

  // 输出排序后的数组
  let sortedArr = new Array(arr.length);
  let j = arr.length - 1;
  for (let i = max; i >= 0; i--) {
    while (counts[i] > 0) {
      sortedArr[j] = i;
      counts[i]--;
      j--;
    }