3.4 KiB
3.4 KiB
前端经典算法
最常用的算法
- 内置的 sort (): 低效
- 快排: 高效
- 插入: n <= 10, 部分有序
冒泡
理解算法用
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n - 1; i++) {
for (let j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// 交换元素
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
// 示例用法
let array = [64, 34, 25, 12, 22, 11, 90];
console.log("排序前: " + array);
let sortedArray = bubbleSort(array);
console.log("排序后: " + sortedArray);
可以进行优化: 如果内层循环一次交换也没发生, 说明已经排序正确, 提前结束
function bubbleSort(arr) {
let n=arr.length
for(i=0; i<n-1; i++) {
let swapen = false
for(j=0; j<n-1-i; j++){
if(arr[j]>arr[j+1]){
let temp = arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
swapen = true
}
}
if(!swapen){
break
}
}
return arr
}
快排
插入
将一个数据插入到已经排好序的有序数据中 扑克牌发牌时的理牌其实就是一种插入排序
- 从第二个位置开始, j 相当于新发的牌
递归
自己调用自己,就是递归 内存的大量占用, 通过占用空间节省运算的时间
==递归很重要的两点==
- 递归入口: 什么时候调用自己(发现相同的问题, 只是规模较小)
- 递归出口:
- 显式出口: 函数通过判断可以明确不用调用
- 函数自动运行完, 没有符合递归的条件
使用:
- 把行政区域信息, 由扁平转为树型
/** *
*
* 将列表型的数据转化成树形数据 => 递归算法 => 自身调用自身 => 一定条件不能一样, 否则就会死循环
* 遍历树形 有一个重点 要先找一个头儿
* ***/
export function tranListToTreeData(list, rootValue) {
let arr = []
list.forEach(item => {
if (item.pid === rootValue) {
// 找到之后 就要去找 item 下面有没有子节点
const children = tranListToTreeData(list, item.id)
if (children.length) {
// 如果children的长度大于0 说明找到了子节点
item.children = children
}
arr.push(item) // 将内容加入到数组中
}
})
return arr
}
- 递归思想:从顶级节点(parentId=0)开始,为每个节点查找其直接子节点
- 终止条件:当找不到更多子节点时,递归结束
- 时间复杂度:O(n^2) 对于每个节点都要遍历整个数组查找子节点
- 优化: 使用 map() 建立映射表
function tranListToTreeData(data, rootValue) {
// 1. 创建id到节点的映射
const nodeMap = new Map();
data.forEach(item => {
nodeMap.set(item.id, { ...item, children: [] });
});
// 2. 构建树结构
const tree = [];
nodeMap.forEach(node => {
if (node.parentId === rootValue) {
tree.push(node);
} else {
const parent = nodeMap.get(node.parentId);
if (parent) {
parent.children.push(node);
}
}
});
return tree;
}