前端也能学算法:JS版链表
时间:2022-07-26
本文章向大家介绍前端也能学算法:JS版链表,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
链表是一种很常见的数据结构,React的Fiber也是采用链表树的数据结构来解决主线程阻塞的问题。它有一个头结点以及多个普通节点组成,每个节点有自己的值,还有一个next属性指向下一个节点,最后一个节点的next为null。链表就通过next将一个个节点连接起来的。
一个典型的JS链表如下:
const NodeD = {
value: 4,
next: null
};
const NodeC = {
value: 3,
next: NodeD
};
const NodeB = {
value: 2,
next: NodeC
};
const NodeA = {
value: 1,
next: NodeB
};
const LinkedList = {
head: NodeA
};
遍历链表
遍历链表是一个很简单的操作,从head开始,通过next一个一个往下走就行,下面我们来实现一下:
// 遍历方法还接收一个参数作为回调,可以用来对每个值进行处理
const traversal = (linkedList, callback) => {
const headNode = linkedList.head;
let currentNode = headNode;
while(currentNode.next) {
callback(currentNode.value);
currentNode = currentNode.next;
}
// 处理最后一个节点的值
callback(currentNode.value);
}
// 测试一下
let total = 0;
const sum = (value) => total = total + value;
traversal(LinkedList, sum);
console.log(total);
复制代码
链表有环
如果我们最后一个节点的next不是null,而是指向第一个节点,我们上面的遍历代码就会陷入死循环。那怎么来判断是不是有环呢?方法其实跟深拷贝处理循环引用很像:
const hasCycle = (linkedList) => {
const map = new WeakMap();
const headNode = linkedList.head;
let current = headNode;
while(current.next){
const exist = map.get(current);
if(exist) return true;
map.set(current, current.value);
current = current.next;
}
return false;
}
// 用这个方法检测下前面的链表
console.log(hasCycle(LinkedList)); // false
// 来检测一个有环的
const NodeB2 = {
value: 2,
};
const NodeA2 = {
value: 1,
next: NodeB2
};
NodeB2.next = NodeA2;
const LinkedList2 = {
head: NodeA2
};
console.log(hasCycle(LinkedList2)); // true
复制代码
Floyd判圈算法
上面的检测方法需要一个map来记录所有遍历过的对象,所以空间复杂度是O(n),还有一个算法可以将空间复杂度降到O(1)。我们可以用两个指针来同时遍历链表,第一个指针的前进速度是1,第二个指针的前进速度是2,如果有环,他们肯定可以相遇:
const hasCycle2 = (linkedList) => {
const headNode = linkedList.head;
let pointer1 = headNode;
let pointer2 = headNode;
while(pointer1.next){
// pointer2跑得快,会先到尾部
// 如果他到尾部了,说明没环
if(!pointer2.next || !pointer2.next.next) {
return false;
}
if(pointer1 === pointer2) {
return ture;
}
pointer1 = pointer1.next;
pointer2 = pointer2.next.next;
}
return false;
}复制代码
原创不易,如果你觉得本文对你有帮助,请点赞支持作者,也让更多人看到本文~~ 更多文章请看我的掘金文章汇总
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法