当前位置:
首页 > temp > JavaScript教程 >
-
前端数据结构--线性结构-链表
链表
标准数组是一块连续的内存地址,所以在做插入、删除时会对数据进行大量的移动,如果数据量很大那么效率会比较低。如果我们把每一个元素都记录着下一个元素的地址,那我们在做插入、删除时是不是只需要改变下一个元素的地址即可, 如
从存储结构来看链表不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用
常见的链表结构有单链表、双向链表、循环链表、双向循环链表。
回到目录
单链表
链表中的每一个节点都具备两个功能:一个功能是存储数据,另外一个功能是记录下一个节点的地址。当结点只记录下一个结点的地址且最后一个结点指向null,这种链表叫单链表。
回到目录
循环链表
循环链表是一种特殊的单链表。它跟单链表的区别就在尾结点。单链表的尾结点指针指向null 空地址,表示这是最后的结点,而循环链表的尾结点指针是指向链表的头结点 如
回到目录
双向链表
单链表只有一个方向,结点只有一个指向后面结点的指针,双向链表支持两个方向,一个是前面,一个是后面 如
回到目录
双向循环链表
把循环链表、双向链表组合就是双向循环链表,结点可以指向前面、后面结点的指针,同时尾结点还指向了头结点 如
回到目录
数组与链表
数组与链表是两种不同的内存组织方式,数组的特点是随机访问、内存地址连续,插入、删除操作不需要移动元素。链表结点要保存上一个结点、下一个结点的信息(对内存的消耗比较大),对于插入、删除操作只需要改变引用的指针即可。
回到目录
js 实现单链表
1 /* 2 数据是1:1的关系 3 单向链表:只有指向一个方向 4 循环链表:末尾节点指向头部节点(跟节点) 5 双向链表:节点存在指向上、下节点的引用 6 双向循环链表:把循环链表、双向链表组合而成 7 */ 8 9 class Node { 10 constructor (data) { 11 this.data = data 12 this.next = null 13 } 14 } 15 16 class linkedList { 17 constructor () { 18 this.header = null 19 this.size = 0 20 } 21 // 插入末尾 22 append (data) { 23 const addNode = new Node(data) 24 if (!this.header) { 25 this.header = addNode 26 } else { 27 const currNode = this.find() 28 currNode.next = addNode 29 } 30 this.size++ 31 } 32 // 插入到x位置,其中是x索引从0开始 33 insertAt (index, data) { 34 if (index < 0 || index > this.size) { 35 throw new Error('插入的位置不正确') 36 } 37 const node = new Node(data) 38 if (index === 0) { 39 node.next = this.header 40 this.header = node 41 } else { 42 let pre = this.getNode(index - 1) 43 node.next = pre.next 44 pre.next = node 45 } 46 this.size++ 47 } 48 // 删除 49 remove (index) { 50 if (index < 0 || index >= this.size) { 51 throw new Error('超出链表索引') 52 } 53 54 if (index === 0) { 55 this.header = this.header.next 56 } else { 57 const pre = this.getNode(index - 1) 58 const delNode = pre.next 59 pre.next = delNode.next 60 } 61 this.size-- 62 } 63 // 通过索引获取 64 getNode (index) { 65 if (index < 0 || index >= this.size) { 66 throw new Error('超出链表索引') 67 } 68 let currentNode = this.header 69 for (let i = 0; i < index; i++) { 70 currentNode = currentNode.next 71 } 72 return currentNode 73 } 74 // 获取末尾节点 75 find () { 76 let currentNode = this.header 77 while (currentNode.next) { 78 currentNode = currentNode.next 79 } 80 return currentNode 81 } 82 } 83 84 const linkList = new linkedList() 85 linkList.append('header') 86 linkList.append(1) 87 linkList.append(2) 88 linkList.append(3) 89 linkList.insertAt(4, 4) 90 linkList.insertAt(3, '3-before') // 插入到3的前面 91 92 linkList.remove(4) 93 console.log(linkList)
对链表的插入、删除操作,在插入第一个结点和删除最后一个结点的情况,需要进行特殊处理,即空链。
本文链接:https://www.cnblogs.com/longbensong/p/14679118.html
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数