返回
JavaScript 数据结构与算法之美
前端
2024-01-29 21:14:52
前言
笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算法和方便以后复习。
文中包含了 十大经典排序算法 的思想、代码实现、一些例子、复杂度分析、动画、还有算法可视化工具。这应该是目前最全的 JavaScript 数据结构与算法教程之一。
十大经典排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 希尔排序
- 归并排序
- 快速排序
- 堆排序
- 计数排序
- 桶排序
- 基数排序
排序算法比较
排序算法 | 时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
冒泡排序 | O(n^2) | O(1) | 是 |
选择排序 | O(n^2) | O(1) | 否 |
插入排序 | O(n^2) | O(1) | 是 |
希尔排序 | O(n log n) | O(1) | 否 |
归并排序 | O(n log n) | O(n) | 是 |
快速排序 | O(n log n) | O(log n) | 否 |
堆排序 | O(n log n) | O(1) | 否 |
计数排序 | O(n + k) | O(k) | 是 |
桶排序 | O(n + k) | O(n + k) | 是 |
基数排序 | O(n * k) | O(n + k) | 是 |
代码实现
十大经典排序算法的 JavaScript 代码实现如下:
// 冒泡排序
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;
}
// 选择排序
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;
}
// 插入排序
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 shellSort(arr) {
let gap = Math.floor(arr.length / 2);
while (gap > 0) {
for (let i = gap; i < arr.length; i++) {
let currentElement = arr[i];
let j = i - gap;
while (j >= 0 && arr[j] > currentElement) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = currentElement;
}
gap = Math.floor(gap / 2);
}
return arr;
}
// 归并排序
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 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;
}
// 快速排序
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
let pivot = arr[0];
let left = [];
let right = [];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return [...quickSort(left), pivot, ...quickSort(right)];
}
// 堆排序
function heapSort(arr) {
let heapSize = arr.length;
// Build a max heap
for (let i = Math.floor(heapSize / 2) - 1; i >= 0; i--) {
heapify(arr, i, heapSize);
}
// Sort the heap
for (let i = heapSize - 1; i >= 0; i--) {
[arr[0], arr[i]] = [arr[i], arr[0]];
heapSize--;
heapify(arr, 0, heapSize);
}
return arr;
}
function heapify(arr, i, heapSize) {
let largest = i;
let left = 2 * i + 1;
let right = 2 * i + 2;
if (left < heapSize && arr[left] > arr[largest]) {
largest = left;
}
if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
[arr[i], arr[largest]] = [arr[largest], arr[i]];
heapify(arr, largest, heapSize);
}
}
// 计数排序
function countingSort(arr, max) {
let counts = new Array(max + 1).fill(0);
for (let i = 0; i < arr.length; i++) {
counts[arr[i]]++;
}
let sortedIndex = 0;
for (let i = 0; i < counts.length; i++) {
while (counts[i] > 0) {
arr[sortedIndex++] = i;
counts[i]--;
}
}
return arr;
}
// 桶排序
function bucketSort(arr, bucketSize) {
let minValue = Math.min(...arr);
let maxValue = Math.max(...arr);
let bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
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] - minValue) / bucketSize);
buckets[bucketIndex].push(arr[i]);
}
for (let i = 0; i < buckets.length; i++) {
buckets[i] = insertionSort(buckets[i]);
}
let sortedIndex