算法
🎯 引言
掌握这些基础算法后,你可以更好地理解数据在程序中的处理方式,提升代码效率,写出更高性能的前端程序。无论是对数据排序,还是从数据中快速查找目标,都能够得心应手。
🧮 排序算法详解
排序算法是前端开发中非常基础且重要的知识。它帮助我们把一组无序的数据变成有序,比如对商品价格排序,或者对时间线进行排列。
下面我们来聊聊几种经典且常用的排序算法。
冒泡排序 Bubble Sort
冒泡排序是最简单的排序算法。它的原理就是在数组中,从头到尾两两比较相邻元素,把大的往后“冒泡”。
想象一下,水里的气泡慢慢往上冒,越大的气泡越容易“浮”到顶部。
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
bubbleSort([5, 4, 2, 1, 3]); // [ 1, 2, 3, 4, 5 ]
选择排序 Selection Sort
选择排序的思路是每次找到数组中最小的那个元素,放到最前面。
可以想象你在挑选苹果,每次都找最小的拿出来放一边。
function selectionSort(arr) {
let len = arr.length;
for (let i = 0; i < len - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex !== i) {
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
}
return arr;
}
selectionSort([5, 4, 2, 1, 3]); // [ 1, 2, 3, 4, 5 ]
插入排序 Insertion Sort
插入排序的思路是把数组分成已排序和未排序两部分,每次把未排序的第一个元素插入到已排序部分合适的位置。
就像整理扑克牌,把新牌插到合适的位置。
function insertionSort(arr) {
let len = arr.length;
for (let i = 1; i < len; i++) {
let key = arr[i];
let j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
return arr;
}
insertionSort([5, 4, 2, 1, 3]); // [ 1, 2, 3, 4, 5 ]
快速排序 Quick Sort
快速排序是一种分治算法,它通过一个“基准”元素把数组分成两部分,一部分比基准小,另一部分比基准大,然后递归排序。
想象分组比赛,先把队伍按实力分成两组,再分别决出胜负。
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)];
}
quickSort([5, 4, 2, 1, 3]); // [ 1, 2, 3, 4, 5 ]
归并排序 Merge Sort
归并排序也是分治思想,把数组一分为二,分别排序后合并。它很适合理解递归结构。
比喻为把一个大拼图拆成小块,分别拼好后再合并。
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, right);
}
function merge(left, right) {
let result = [];
let i = 0,
j = 0;
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
result.push(left[i++]);
} else {
result.push(right[j++]);
}
}
return result.concat(left.slice(i)).concat(right.slice(j));
}
mergeSort([5, 4, 2, 1, 3]); // [ 1, 2, 3, 4, 5 ]
🔍 查找算法详解
查找算法是前端中获取数据的常用操作。比如在列表中找某个用户,或者定位某条记录。
线性查找 Linear Search
线性查找是最简单的查找方法,逐个遍历元素,找到目标就返回。
就像你翻书找某句话,一页一页往下看。
function linearSearch(arr, target) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
return i;
}
}
return -1;
}
linearSearch([5, 4, 2, 1, 3], 1); // 3
二分查找 Binary Search
二分查找适合有序数组,先看中间元素,判断目标是在左边还是右边,再递归缩小范围。
就像你用字典查单词,先翻中间那页,对比大小后缩小查找范围。
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
binarySearch([1, 2, 3, 4, 5], 3); // 2
🧾 小节总结
- 冒泡、选择、插入排序适合小规模数据,理解简单但效率较低。
- 快速排序和归并排序适合大规模数据,时间复杂度均为 O(n log n)。
- 查找算法中,线性查找适合无序数据,二分查找适合有序数据,效率明显提升。
❓ 知识问答(Q&A)
Q:冒泡排序为什么效率低?
A:因为它需要多次比较和交换,时间复杂度是 O(n²),数据量大时运行慢。
Q:二分查找能用于无序数组吗?
A:不能,二分查找的前提条件是数组必须排序,否则无法保证左右半边的有序性。
🎉 恭喜你已经掌握 冒泡排序、快速排序、二分查找 等基础算法技能啦! 期待你用它们写出更高效的前端程序!
