链表相较于数组的优缺点

1. 链表在 插入、删除、移动数据效率比数组要高,数组插入、移动、删除数据需要改变没有数据的索引,而链表则只需要更改指针即可

2. 在查询方面,数组要优于链表,数组存储的数据是连续的,可以直接通过位置信息读取到数据,而链表则需要通过遍历的方式找到对应的指针

3. 灵活性方面,传统的数组是需要固定长度的,而链表则可以是任意长度

备注:JavaScript中会根据实际情况,将数组转换为 快数组或者慢数组(掘金的文章:https://juejin.cn/post/6844903943638794248#heading-0

链表图解:

链表实现(实现了循环链表、双向链表、单项链表):

// 创建链表
class Node {
constructor(element) {
this.element = element
this.next = null
// 实现双向链表指针
this.prev = null
}
}
class SingleList {
constructor() {
this.size = 0
this.head = null
this.tail = this.head
} // 在尾部添加元素
append(element) {
const newNode = new Node(element)
// 实现循环链表(其实就是将最后一个元素的指针指向 head)
// newNode.next = this.head
if (!this.head) {
this.head = newNode
} else {
this.tail.next = newNode
newNode.prev = this.tail
} this.tail = newNode
this.size++
}
  // 对 size 进行缓存,获取长度的时候直接返回即可
getLength() {
return this.size
} find(element) {
let _elm = this.head
let i = 0
// while(_elm) {} 因为实现了循环链表,_elm不可能为空
while (i < this.size) {
if (_elm.element === element) {
return _elm
} _elm = _elm.next
i++
} return null
}
// 删除指定元素
remove(element) {
const _delItem = this.find(element) if(!_delItem) {
return false
}
    // 通过改变指针选项实现
const _oldNext = _delItem.next
const prev = _delItem.prev
prev.next = _oldNext return true
}
  // 或者最后一个元素,this.tail 已经进行缓存,故直接返回即可
findLast() { return this.tail } insert(newItem, posItem) {
if (posItem) {
const pos = this.find(posItem)
if (!pos) {
return false
}
       // 通过改变指针指向实现插入元素
const oldNext = pos.next
const newNext = new Node(newItem)
newNext.prev = pos
newNext.next = oldNext
pos.next = newNext
} else {
this.append(newItem)
}
}
}

  

链表拓展算法:

1. 链表反转

function reverse(head) {
let _newHead = null while(head) {
const tmp = head.next
head.next = _newHead
_newHead = head
head = tmp
} return _newHead
} // 模拟一个链表格式
const head = {"element":1,"next":{"element":2,"next":{"element":3,"next":null}}}
reverse(head)
// 分析一波:
// 第一次while(head = {"element":1,"next":{"element":2,"next":{"element":3,"next":null}}}):
// const tmp = head.next // tmp -> {"element":2,"next":{"element":3,"next":null}}
// head.next = _newHead // head -> {"element":1,"next": null }
// _newHead = head // _newHead -> {"element":1,"next": null }
// head = tmp // head -> {"element":2,"next":{"element":3,"next":null}} // 第二次while(head = {"element":2,"next":{"element":3,"next":null}}):
// const tmp = head.next // tmp -> {"element":3,"next":null}
// head.next = _newHead // head -> {"element":2,"next": {"element":1,"next": null }}
// _newHead = head // _newHead -> {"element":2,"next": {"element":1,"next": null }}
// head = tmp // head -> {"element":3,"next":null} // 第三次while(head = {"element":3,"next":null}):
// const tmp = head.next // tmp -> null
// head.next = _newHead // head -> {"element":3,"next":{"element":2,"next": {"element":1,"next": null }}}
// _newHead = head // _newHead -> {"element":3,"next":{"element":2,"next": {"element":1,"next": null }}}
// head = tmp // head -> null

  

2. 判断是否为回文链表

备注:这里使用 快慢指针 的方式实现 时间复杂度O(n),空间复杂度O(1),也可以先将链表转为数组实现,时间复杂度O(n) 空间复杂度O(n)

// 判断是否是 回文链表
function isPalindrome(head) {
if(!head || !head.next) {
return true
}
let fast = head;
let slow = head;
let prev;
while (fast && fast.next) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
// 断开链表
prev.next = null // 翻转后半段链表
let head2 = null
while(slow) {
const tmp = slow.next
slow.next = head2
head2 = slow
slow = tmp
} // 对比
while(head && head2) {
if(head.element !== head2.element) {
return false
}
head = head.next
head2 = head2.next
} return true
}

  

JavaScript数据结构之链表的更多相关文章

  1. 学习javascript数据结构(二)——链表

    前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...

  2. JavaScript数据结构-7.链表

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 学习javascript数据结构(三)——集合

    前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...

  4. 学习javascript数据结构(四)——树

    前言 总括: 本文讲解了数据结构中的[树]的概念,尽可能通俗易懂的解释树这种数据结构的概念,使用javascript实现了树,如有纰漏,欢迎批评指正. 原文博客地址:学习javascript数据结构( ...

  5. JavaScript数据结构——链表

    链表:存储有序的元素集合,但不同于数组,链表中的元素在内存中不是连续放置的.每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 好处:可以添加或移除任意项,它会按需扩容 ...

  6. 为什么我要放弃javaScript数据结构与算法(第五章)—— 链表

    这一章你将会学会如何实现和使用链表这种动态的数据结构,这意味着我们可以从中任意添加或移除项,它会按需进行扩张. 本章内容 链表数据结构 向链表添加元素 从链表移除元素 使用 LinkedList 类 ...

  7. JavaScript数据结构与算法-链表练习

    链表的实现 一. 单向链表 // Node类 function Node (element) { this.element = element; this.next = null; } // Link ...

  8. 重读《学习JavaScript数据结构与算法-第三版》- 第6章 链表(一)

    定场诗 伤情最是晚凉天,憔悴厮人不堪言: 邀酒摧肠三杯醉.寻香惊梦五更寒. 钗头凤斜卿有泪,荼蘼花了我无缘: 小楼寂寞新雨月.也难如钩也难圆. 前言 本章为重读<学习JavaScript数据结构 ...

  9. JavaScript 数据结构与算法之美 - 线性表(数组、栈、队列、链表)

    前言 基础知识就像是一座大楼的地基,它决定了我们的技术高度. 我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一. 栈.队列.链表.堆 是数据结构与算法中的基 ...

随机推荐

  1. 【LeetCode】654. Maximum Binary Tree 解题报告 (Python&C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...

  2. 1434 区间LCM

    1434 区间LCM 基准时间限制:1 秒 空间限制:131072 KB 一个整数序列S的LCM(最小公倍数)是指最小的正整数X使得它是序列S中所有元素的倍数,那么LCM(S)=X. 例如,LCM(2 ...

  3. 如何让 Spring Security 「少管闲事」

    记两种让 Spring Security「少管闲事」的方法. 遇到问题 一个应用对外提供 Rest 接口,接口的访问认证通过 Spring Security OAuth2 控制,token 形式为 J ...

  4. Arm64架构下静态编译Nginx

    这段时间,我一直忙于将 Rainbond 源码构建模块移植到 Arm64/aarch64 架构中.这一源码构建模块可以将指定代码仓库中包含的源码,拉取构建成为容器镜像,在各种容器平台中运行.目前支持的 ...

  5. 为什么加密后的数据往往都是base64输出而不是hex16进制输出

    通常加密后的数据都是字节数组,比如流行的aes128对称加密,还有Rsa非对称加密,加密后得到了一个字节数组,这个字节数组存在内存中,往往我们需要输出得到我们人眼能看到的字符. 加密aes(xxx) ...

  6. 浅谈JVM内存分配与垃圾回收

    大家好,我是微尘,最近又去翻了周志明老师的<深入理解Java虚拟机>这本书.已经看了很多遍了,每次都感觉似乎看懂了,但没过多久就忘了.这次翻了第三章的垃圾收集器与内存分配策略,感觉有了新的 ...

  7. 【jvm】05-为什么你写的代码有时候和预期不一致

    [jvm]05-为什么你写的代码有时候和预期不一致 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请 ...

  8. Java的generator工具类,数据库生成实体类和映射文件

    首先需要几个jar包: freemarker-2.3.23.jar log4j-1.2.16.jar mybatis-3.2.3.jar mybatis-generator-core-1.3.2.ja ...

  9. Swoole 中使用 TCP 异步服务器、TCP 协程服务器、TCP 同步客户端、TCP 协程客户端

    TCP 异步风格服务器 异步风格服务器通过监听事件的方式来编写程序.当对应的事件发生时底层会主动回调指定的函数. 由于默认开启协程化,在回调函数内部会自动创建协程,遇到 IO 会产生协程调度,异步风格 ...

  10. Linux_yum安装时报404错误

    使用yum安装报错如下: [root@localhost ~]# yum install gcc 已加载插件:fastestmirror Loading mirror speeds from cach ...