返回

前端面试常考的10大排序算法 助你轻松应对面试

前端

前端面试必考:10 大排序算法详解

简介

排序算法是一种将数据按照特定顺序排列的算法。在前端开发中,掌握基本的排序算法思想至关重要,尤其是对于大型数据处理和优化用户体验。本文将深入探讨前端面试中常考的 10 大排序算法,帮助你提升算法技能,在求职中脱颖而出。

1. 插入排序

插入排序是一种简单的排序算法,通过将待排序元素逐个插入到已排序的子序列中,从而完成排序。插入排序的时间复杂度为 O(n^2),空间复杂度为 O(1),适合于小规模数据集的排序。

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

2. 冒泡排序

冒泡排序是一种直观的排序算法,通过比较相邻元素,将较小的元素“冒泡”到数组前端。冒泡排序的时间复杂度为 O(n^2),空间复杂度为 O(1),适合于教学或小型数据集的排序。

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

3. 选择排序

选择排序通过不断找出待排序数组中的最小元素,并将其交换到数组首部,从而完成排序。选择排序的时间复杂度为 O(n^2),空间复杂度为 O(1),适合于小规模数据集的排序。

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

4. 快速排序

快速排序是一种高效的排序算法,通过选择一个基准元素,将数组分为两个子数组,并将基准元素放在中间位置,然后递归地对子数组进行排序。快速排序的时间复杂度为 O(n log n),空间复杂度为 O(log n),适合于大规模数据集的排序。

function quickSort(arr, left, right) {
  if (left < right) {
    let pivotIndex = partition(arr, left, right);
    quickSort(arr, left, pivotIndex - 1);
    quickSort(arr, pivotIndex + 1, right);
  }
  return arr;
}

function partition(arr, left, right) {
  let pivot = arr[right];
  let i = left - 1;
  for (let j = left; j < right; j++) {
    if (arr[j] < pivot) {
      i++;
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
  }
  [arr[i + 1], arr[right]] = [arr[right], arr[i + 1]];
  return i + 1;
}

5. 归并排序

归并排序是一种稳定的排序算法,通过将数组分成两半,递归地对每一半进行排序,然后合并两个有序的子数组,从而完成排序。归并排序的时间复杂度为 O(n log n),空间复杂度为 O(n),适合于大规模数据集的排序。

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

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

6. 堆排序

堆排序是一种不稳定的排序算法,通过将数组构建成一个堆,并不断将堆顶元素与堆底元素交换,从而完成排序。堆排序的时间复杂度为 O(n log n),空间复杂度为 O(1),适合于大规模数据集的排序。

function heapSort(arr) {
  buildMaxHeap(arr);
  for (let i = arr.length - 1; i >= 1; i--) {
    [arr[0], arr[i]] = [arr[i], arr[0]];
    heapify(arr, 0, i);
  }
  return arr;
}

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

function heapify(arr, i, size) {
  let left = 2 * i + 1;
  let right = 2 * i + 2;
  let largest = i;
  if (left < size && arr[left] > arr[largest]) {
    largest = left;
  }
  if (right < size && arr[right] > arr[largest]) {
    largest = right;
  }
  if (largest != i) {
    [arr[i], arr[largest]] = [arr[largest], arr[i]];
    heapify(arr, largest, size);
  }
}

7. 计数排序

计数排序是一种稳定的排序算法,适用于范围有限的非负整数数组。计数排序的时间复杂度为 O(n + k),其中 k 是数组中最大值的范围,空间复杂度为 O(k)。

function countingSort(arr, maxValue) {
  let count = new Array(maxValue + 1).fill(0);
  for (let i = 0; i < arr.length; i++) {
    count[arr[i]]++;
  }
  let sortedIndex = 0;
  for (let i = 0; i < count.length; i++) {
    while (count[i] > 0) {
      arr[sortedIndex] = i;
      sortedIndex++;
      count[i]--;
    }
  }
  return arr;
}

8. 桶排序

桶排序是一种不稳定的排序算法,适用于数据分布均匀的数据集。桶排序的时间复杂度为 O(n + k),其中 k 是桶的个数,空间复杂度为 O(n + k)。

function bucketSort(arr, bucketSize) {
  let maxValue = Math.max(...arr);
  let bucketCount = Math.ceil(maxValue / bucketSize);
  let buckets = new Array(bucketCount);
  for (let i = 0; i < buckets.length; i++) {
    buckets[i] = [];
  }
  for (let i = 0; i < arr.length; i++) {
    let bucketIndex = Math.floor(arr[i] / bucketSize);
    buckets[bucketIndex].push(arr[i]);
  }
  let sortedIndex = 0;
  for (let i = 0; i < buckets.length; i++) {
    insertionSort(buckets[i]);
    for (let j = 0; j < buckets[i].length; j++) {
      arr[sortedIndex] = buckets[i][j];
      sorted