js 实现数据结构 -- 链表(LinkedList)
原文:
概念:
链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个 元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。下图展示了链表的结构:
相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。然而,链表需要使用指针,因此实现链表时需要额外注意。 数组的另一个细节是可以直接访问任何位置的任何元素,而要想访问链表中间的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素。
普通链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | // 链表节点 class Node { constructor(element) { this .element = element; this .next = null ; } } // 链表 class LinkedList { constructor() { this .head = null ; this .length = 0; // length 同数组 length 与下标关系 } // 追加元素 append(element) { let node = new Node(element); let current = null ; // 指针? if ( this .head === null ) { this .head = node; } else { current = this .head; while (current.next) { current = current.next; } current.next = node; } this .length++; } // 任意位置插入元素 insert (position, element) { if (position >= 0 && position <= this .length) { let node = new Node(element); let current = this .head; let previous = null ; let index = 0; if (position === 0) { this .head = node; } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } this .length++; return true } return false } // 移除指定位置元素 removeAt(position) { if (position > -1 && position < length) { let current = this .head; let previous = null ; let index = 0; if (position === 0) { this .head = current.next; } else { while (index++ < position) { previous = current; current = current.next; } previous.next = current.next; } this .length--; return current.element; } return null } // 寻找元素下标 findIndex(element) { let current = this .head; let index = -1; while (current) { if (element === current.element) { return index + 1; } index++; current = current.next; } return -1; } // 删除指定文档 remove(element) { let index = this .findIndex(element); return removeAt(index); } isEmpty() { return ! this .length; } size() { return this .length; } // 输出字符串 toString() { let current = this .head; let string = '' ; while (current) { string += ` ${current.element}`; current = current.next; } return string; } } var ll = new LinkedList(); console.log(ll); ll.append(2); ll.append(6); ll.append(24); ll.append(152); ll.insert(3, 18); console.log(ll); console.log(ll.findIndex(24)); |
双向链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | class Node { constructor(element) { this .element = element; this .prev = null ; this .next = null ; } } // 双向链表 class DoubleLinkedList { constructor() { this .head = null ; this .tail = null ; this .length = 0; } // 任意位置插入元素 insert(position, element) { if (position >= 0 && position <= ehis.length) { let node = new Node(element); let current = this .head; let previous = null ; this .index = 0; // 首位 if (position === 0) { if (!head) { this .head = node; this .tail = node; } else { node.next = current; this .head = node; current.prev = node; } } else if (position === this .length) { // 末尾 current = this .tail; current.next = node; node.prev = current; this .tail = node; } else { // 中间 while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; current.prev = node; node.prev = previous; } this .length++; return true ; } return false ; } // 移除指定位置元素 removeAt(position) { if (position > -1 && position < this .length) { let current = this .head; let previous = null ; let index = 0; // 首位 if (position === 0) { this .head = this .head.next this .head.prev = null if ( this .length === 1) { this .tail = null } } else if (position === this .length - 1) { // 末位 this .tail = this .tail.prev this .tail.next = null } else { // 中位 while (index++ < position) { previous = current current = current.next } previous.next = current.next current.next.prev = previous } this .length--; return current.element; } else { return null ; } } // 其他方法 } |
循环链表:
具体代码实现就不写了,下图是示意图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码