文章目录
好的,下面是更详细的 JavaScript 经典算法实现,包含了更多的算法示例,并对每个代码进行了注释,帮助理解每一步的实现过程。
1. 冒泡排序(Bubble Sort)
冒泡排序是一种通过反复遍历待排序数组,比较相邻的元素并交换它们,直到数组有序的排序方法。
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n; i++) {
// 每次遍历,从0到n-i-1,i是已经排序好的元素个数
for (let j = 0; j < n - i - 1; j++) {
// 如果相邻元素逆序,则交换它们
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
2. 选择排序(Selection Sort)
选择排序通过不断选择未排序部分中的最小(或最大)元素,将其与未排序部分的第一个元素交换。
function selectionSort(arr) {
let n = arr.length;
for (let i = 0; i < n; i++) {
let minIndex = i;
for (let j = i + 1; j < n; j++) {
// 找到未排序部分中的最小元素
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换当前元素和最小元素
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
3. 插入排序(Insertion Sort)
插入排序通过将每个元素插入到已排序部分的正确位置来完成排序。
function insertionSort(arr) {
for (let i = 1; i < arr.length; i++) {
let current = arr[i];
let j = i - 1;
// 将当前元素插入到前面的已排序部分
while (j >= 0 && arr[j] > current) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = current;
}
return arr;
}
4. 快速排序(Quick Sort)
快速排序通过选择一个基准元素,将数组分成两部分,其中一部分的所有元素都比基准小,另一部分都比基准大,然后递归排序这两部分。
function quickSort(arr) {
if (arr.length <= 1) return arr; // 如果数组长度小于等于1,直接返回数组
const pivot = arr[arr.length - 1]; // 选择数组最后一个元素作为基准
let left = [], 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)];
}
5. 二分查找(Binary Search)
二分查找是一种高效的查找方法,前提是数组必须已经排好序。通过每次将查找范围折半来缩小查找范围。
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid; // 找到目标元素
}
if (arr[mid] < target) {
left = mid + 1; // 目标在右半部分
} else {
right = mid - 1; // 目标在左半部分
}
}
return -1; // 没有找到目标元素
}
6. 斐波那契数列(Fibonacci Sequence)
斐波那契数列是一个经典的递归问题,数列中的每个数字都是前两个数字之和。可以通过递归、动态规划和迭代等方法求解。
递归实现:
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2); // 递归调用
}
动态规划实现:
function fibonacciDP(n) {
if (n <= 1) return n;
let fib = [0, 1];
for (let i = 2; i <= n; i++) {
fib[i] = fib[i - 1] + fib[i - 2]; // 每次计算当前元素
}
return fib[n];
}
7. 反转字符串(Reverse String)
通过不同的方法反转一个字符串。
使用 split
、reverse
和 join
:
function reverseString(str) {
return str.split('').reverse().join(''); // 拆分字符串,反转,合并
}
使用循环:
function reverseString(str) {
let result = '';
for (let i = str.length - 1; i >= 0; i--) {
result += str[i]; // 从后往前遍历字符并拼接
}
return result;
}
8. 判断回文(Palindrome)
回文是指正着读和反着读都一样的字符串。判断一个字符串是否是回文可以通过比对字符串的两端来实现。
function isPalindrome(str) {
const reversedStr = str.split('').reverse().join('');
return str === reversedStr; // 比较原字符串和反转后的字符串
}
9. 求最大公约数(GCD)
最大公约数是能同时整除两个数的最大整数。可以使用欧几里得算法来求解。
function gcd(a, b) {
while (b !== 0) {
let temp = b;
b = a % b; // 求余数
a = temp; // 更新a和b
}
return a; // 返回最大公约数
}
10. 深拷贝(Deep Clone)
深拷贝是创建一个新的对象,新的对象完全复制原对象的结构和数据。
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj; // 不是对象直接返回
let copy;
if (Array.isArray(obj)) {
copy = [];
for (let i = 0; i < obj.length; i++) {
copy[i] = deepClone(obj[i]); // 递归处理数组中的元素
}
} else {
copy = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key]); // 递归处理对象中的属性
}
}
}
return copy;
}
11. 计数排序(Counting Sort)
计数排序是一个基于元素计数的排序算法,适用于范围有限的整数排序。
function countingSort(arr) {
let max = Math.max(...arr); // 找到数组中的最大值
let count = new Array(max + 1).fill(0); // 创建计数数组
arr.forEach(num => count[num]++); // 统计每个元素出现的次数
let result = [];
for (let i = 0; i < count.length; i++) {
while (count[i] > 0) {
result.push(i);
count[i]--;
}
}
return result;
}
12. 异或交换两个数
通过异或操作交换两个数的值,不需要临时变量。
function swap(a, b) {
a ^= b;
b ^= a;
a ^= b; // 通过异或交换值
return [a, b];
}
13. 合并两个有序数组
将两个有序数组合并成一个新的有序数组。
function mergeSortedArrays(arr1, arr2) {
let result = [];
let i = 0, j = 0;
// 合并过程
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
result.push(arr1[i]);
i++;
} else {
result.push(arr2[j]);
j++;
}
}
// 处理剩余部分
return result.concat(arr1.slice(i), arr2.slice(j));
}
### 总结
这些经典的 JavaScript 算法涵盖了排序、查找、递归、字符串处理、数学问题等基本问题。掌握这些算法的实现有助于提升编程能力,并且能帮助你更好地理解数据结构和算法的设计思想。