JavaScript算法大揭秘:排序篇
2023-11-27 18:45:31
前言
算法是计算机科学的核心,排序算法是其中最基础也是最重要的算法之一。排序算法的作用是将一组数据按照某种顺序排列,以便于查找、比较和分析。在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