(五)数据结构之“链表”

链表是什么?

多个元素组成的列表
元素存储不连续,用next指针连在一起
在这里插入图片描述

数组 vs 链表

数组:增删非首尾元素是往往需要移动元素
链表:增删非首尾元素,不需要移动元素,只需要更改next的指向即可

JS中的链表

JavaScript中没有链表
可以用Object模拟链表

const a = { val: 'a' };
const b = { val: 'b' };
const c = { val: 'c' };
const d = { val: 'd' };
a.next = b;
b.next = c;
c.next = d;

// 遍历链表
let p = a;
while (p) {
    console.log(p.val);
    p = p.next;
}

// 插入
const e = { val: 'e' };
c.next = e;
e.next = d;

// 删除
c.next = d;

LeetCode:237.删除链表中的节点

在这里插入图片描述

解题思路
无法直接获取被删除节点的上个节点
将被删除节点转移到下个节点
解题步骤
将被删节点的值改为下个节点的值
删除下个节点
在这里插入图片描述
时间复杂度O(1),空间复杂度O(1)

LeetCode:206.反转链表

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

解题思路
反转两个节点:将n + 1的next指向n
反转多个节点:双指针遍历链表,重复上述操作

解题步骤
双指针一前一后遍历链表
反转双指针
在这里插入图片描述
时间复杂度O(n),空间复杂度O(1)

LeetCode:2.两数相加

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解题思路
小学数学题,模拟相加操作
需要遍历链表

解题步骤
新建一个空链表
遍历被相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加
在这里插入图片描述
时间复杂度O(n),空间复杂度O(n)

LeetCode:83.删除排序链表中的重复元素

输入:1 -> 1 -> 2
输出:1 -> 2

解题思路
因为链表是有序的,所以重复元素一定相邻
遍历链表,如果发现当前元素和下个元素值相同,就删除下个元素值

解题步骤
遍历链表,如果发现当前元素和下个元素值相同,就删除下个元素值
遍历结束后,返回原链表的头部
在这里插入图片描述
时间复杂度O(n),空间复杂度O(1)

LeetCode:141.环形链表

在这里插入图片描述
解题思路
两个人在圆形操场上的起点同时起跑,速度快的人一定会超过速度慢的人一圈
用一快一慢两个指针遍历链表,如果指针能够相逢,那么链表就有圈

解题步骤
用一快一慢两个指针遍历链表,如果指针能够相逢,就返回true
遍历结束后,还没有相逢就返回false
在这里插入图片描述
时间复杂度O(n),空间复杂度O(1)

前端与链表(JS中的原型链)

原型链简介
原型链的本质是链表
原型链上的节点是各种原型对象,比如Function.prototype、Object.prototype…
原型链通过__proto__属性链接各种原型对象
原型链长啥样
obj -> Object.prototype -> null
func -> Function.prototype -> Object.prototype -> null
arr -> Array.prototype -> Object.prototype -> null
原型链知识点
如果A沿着原型链能找到B的原型对象(B.prototype),那么A instanceof B为true
如果在A对象上没有找到x属性,那么会沿着原型链找x属性

const obj = {}
const func = () => {}
const arr = []
//原型链通过__proto__属性链接各种原型对象
console.log(obj .__proto__ === Object.prototype) //true
console.log(func.__proto__ === Function.prototype) //true
console.log(func.__proto__.__proto__ === Object.prototype) //true
console.log(arr.__proto__ === Array.prototype) //true
console.log(arr.__proto__.__proto__ === Object.prototype) //true

//如果A沿着原型链能找到B的原型对象(B.prototype),那么A instanceof B为true
console.log(func instanceof Function) //true
console.log(func instanceof Object) //true
//fuc的proto属性指向Function的原型对象,
//func即是object的实例,也是function的实例

//如果在A对象上没有找到x属性,那么会沿着原型链找x属性
const obj = {};
Object.prototype.x = 'x'
const func = () => {};
Function.prototype.y = 'y'
console.log(obj.x) //x
console.log(obj.y) //undefined
console.log(func.x) //x
console.log(func.y) //y

一、instanceof的使用,并用代码实现

分析
知识点:如果A沿着原型链能找到B.prototype,那么A instanceof B为true
解法:遍历A的原型链,如果找到B.prototype,返回true,否则返回false

const instanceOf = (A,B) => {
	let p = A;
	while (p) {
		if (p === B.prototype) {
			return true;
		}
		p = p.__proto__;
	}
	return false;
}
 

var foo = {},F = Function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b'

console.log(foo.a)
console.log(foo.b)

console.log(F.a)
console.log(F.b)
 

分析
知识点:如果在A对象上没有找到x属性,那么会沿着原型链找x属性
解法:明确foo和F变量的原型链,沿着原型链找a属性和b属性

前端链表:使用链表指针获取JSON的节点值

const json = {
	a: { b: { c: 1 } },
	d: { e: 2 },  
}
const path = ['a', 'b' ,'c']
let p =json;
path.forEach(k => {
	p = p[k];
})
 

总结

链表里的元素存储不是连续的,之间通过next连接
JavaScript中没有链表,但可以用Object模拟链表
链表常用操作:修改next、遍历链表
JS中的原型链也是一个链表
使用链表指针可以获取JSON的节点值

思考题

1、编写一个 instanceOf 方法,可以判断一个变量是否是另一个变量的实例
2、请判断一个链表是否为回文链表。题目链接:https://leetcode-cn.com/problems/palindrome-linked-list/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值