data-structure-typed 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/COMMANDS.md +17 -0
  3. package/benchmark/report.html +13 -77
  4. package/benchmark/report.json +145 -177
  5. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
  6. package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
  7. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  8. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
  9. package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  11. package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
  12. package/dist/cjs/data-structures/base/linear-base.js +137 -274
  13. package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
  14. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  15. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
  16. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  17. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  18. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  19. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  20. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
  21. package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
  22. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  23. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
  24. package/dist/cjs/data-structures/binary-tree/binary-tree.js +594 -865
  25. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  26. package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
  27. package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
  28. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  29. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  30. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
  31. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  32. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
  33. package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
  34. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  35. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  36. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
  37. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  38. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
  39. package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
  40. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  41. package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
  42. package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
  43. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  44. package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
  45. package/dist/cjs/data-structures/graph/map-graph.js +56 -59
  46. package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
  47. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
  48. package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
  49. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  50. package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
  51. package/dist/cjs/data-structures/hash/hash-map.js +270 -457
  52. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  53. package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
  54. package/dist/cjs/data-structures/heap/heap.js +340 -349
  55. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  56. package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
  57. package/dist/cjs/data-structures/heap/max-heap.js +11 -66
  58. package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
  59. package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
  60. package/dist/cjs/data-structures/heap/min-heap.js +11 -66
  61. package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
  62. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  63. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
  64. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  65. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  66. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
  67. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  68. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  69. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
  70. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  71. package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  72. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
  73. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  74. package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  75. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
  76. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  77. package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
  78. package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
  79. package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
  80. package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
  81. package/dist/cjs/data-structures/queue/deque.js +309 -348
  82. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  83. package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
  84. package/dist/cjs/data-structures/queue/queue.js +265 -248
  85. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  86. package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
  87. package/dist/cjs/data-structures/stack/stack.js +181 -125
  88. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  89. package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
  90. package/dist/cjs/data-structures/trie/trie.js +189 -172
  91. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  92. package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
  93. package/dist/cjs/interfaces/graph.d.ts +16 -0
  94. package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
  95. package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
  96. package/dist/cjs/types/utils/utils.d.ts +1 -0
  97. package/dist/cjs/utils/utils.d.ts +1 -1
  98. package/dist/cjs/utils/utils.js +2 -1
  99. package/dist/cjs/utils/utils.js.map +1 -1
  100. package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
  101. package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
  102. package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
  103. package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
  104. package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
  105. package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
  106. package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
  107. package/dist/esm/data-structures/base/linear-base.js +137 -274
  108. package/dist/esm/data-structures/base/linear-base.js.map +1 -1
  109. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  110. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
  111. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  112. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  113. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
  114. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  115. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
  116. package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
  117. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  118. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
  119. package/dist/esm/data-structures/binary-tree/binary-tree.js +598 -874
  120. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  121. package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
  122. package/dist/esm/data-structures/binary-tree/bst.js +507 -487
  123. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  124. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  125. package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
  126. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  127. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
  128. package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
  129. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  130. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  131. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
  132. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  133. package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
  134. package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
  135. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  136. package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
  137. package/dist/esm/data-structures/graph/directed-graph.js +145 -233
  138. package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
  139. package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
  140. package/dist/esm/data-structures/graph/map-graph.js +56 -59
  141. package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
  142. package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
  143. package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
  144. package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
  145. package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
  146. package/dist/esm/data-structures/hash/hash-map.js +270 -457
  147. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  148. package/dist/esm/data-structures/heap/heap.d.ts +214 -289
  149. package/dist/esm/data-structures/heap/heap.js +329 -349
  150. package/dist/esm/data-structures/heap/heap.js.map +1 -1
  151. package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
  152. package/dist/esm/data-structures/heap/max-heap.js +11 -66
  153. package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
  154. package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
  155. package/dist/esm/data-structures/heap/min-heap.js +11 -66
  156. package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
  157. package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  158. package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
  159. package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  160. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  161. package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
  162. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  163. package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  164. package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
  165. package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
  166. package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  167. package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
  168. package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  169. package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  170. package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
  171. package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  172. package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
  173. package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
  174. package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
  175. package/dist/esm/data-structures/queue/deque.d.ts +227 -254
  176. package/dist/esm/data-structures/queue/deque.js +313 -348
  177. package/dist/esm/data-structures/queue/deque.js.map +1 -1
  178. package/dist/esm/data-structures/queue/queue.d.ts +180 -201
  179. package/dist/esm/data-structures/queue/queue.js +263 -248
  180. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  181. package/dist/esm/data-structures/stack/stack.d.ts +124 -102
  182. package/dist/esm/data-structures/stack/stack.js +181 -125
  183. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  184. package/dist/esm/data-structures/trie/trie.d.ts +164 -165
  185. package/dist/esm/data-structures/trie/trie.js +193 -172
  186. package/dist/esm/data-structures/trie/trie.js.map +1 -1
  187. package/dist/esm/interfaces/binary-tree.d.ts +56 -6
  188. package/dist/esm/interfaces/graph.d.ts +16 -0
  189. package/dist/esm/types/data-structures/base/base.d.ts +1 -1
  190. package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
  191. package/dist/esm/types/utils/utils.d.ts +1 -0
  192. package/dist/esm/utils/utils.d.ts +1 -1
  193. package/dist/esm/utils/utils.js +2 -1
  194. package/dist/esm/utils/utils.js.map +1 -1
  195. package/dist/umd/data-structure-typed.js +4685 -6477
  196. package/dist/umd/data-structure-typed.min.js +8 -6
  197. package/dist/umd/data-structure-typed.min.js.map +1 -1
  198. package/package.json +3 -4
  199. package/src/data-structures/base/iterable-element-base.ts +238 -115
  200. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  201. package/src/data-structures/base/linear-base.ts +271 -277
  202. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  203. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  204. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  205. package/src/data-structures/binary-tree/binary-tree.ts +660 -889
  206. package/src/data-structures/binary-tree/bst.ts +568 -570
  207. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  208. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  209. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  210. package/src/data-structures/graph/abstract-graph.ts +339 -264
  211. package/src/data-structures/graph/directed-graph.ts +146 -236
  212. package/src/data-structures/graph/map-graph.ts +63 -60
  213. package/src/data-structures/graph/undirected-graph.ts +129 -152
  214. package/src/data-structures/hash/hash-map.ts +274 -496
  215. package/src/data-structures/heap/heap.ts +389 -402
  216. package/src/data-structures/heap/max-heap.ts +12 -76
  217. package/src/data-structures/heap/min-heap.ts +13 -76
  218. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  219. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  220. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  221. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  222. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  223. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  224. package/src/data-structures/queue/deque.ts +381 -357
  225. package/src/data-structures/queue/queue.ts +310 -264
  226. package/src/data-structures/stack/stack.ts +217 -131
  227. package/src/data-structures/trie/trie.ts +240 -175
  228. package/src/interfaces/binary-tree.ts +240 -6
  229. package/src/interfaces/graph.ts +37 -0
  230. package/src/types/data-structures/base/base.ts +5 -5
  231. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  232. package/src/types/utils/utils.ts +2 -0
  233. package/src/utils/utils.ts +9 -14
  234. package/test/integration/index.html +1 -1
  235. package/test/performance/benchmark-runner.ts +528 -0
  236. package/test/performance/reportor.mjs +43 -43
  237. package/test/performance/runner-config.json +39 -0
  238. package/test/performance/single-suite-runner.ts +69 -0
  239. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
  240. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
  241. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
  242. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
  243. package/test/unit/data-structures/binary-tree/bst.test.ts +12 -9
  244. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
  245. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
  246. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
  247. package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
  248. package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
  249. package/test/unit/data-structures/heap/heap.test.ts +14 -21
  250. package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
  251. package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
  252. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
  253. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
  254. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
  255. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
  256. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
  257. package/test/unit/data-structures/queue/queue.test.ts +4 -5
  258. package/test/unit/utils/utils.test.ts +0 -1
  259. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
  260. package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
@@ -1,9 +1,22 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
1
8
  import { LinearLinkedBase, LinkedListNode } from '../base/linear-base';
9
+ /**
10
+ * Node of a doubly linked list; stores value and prev/next links.
11
+ * @remarks Time O(1), Space O(1)
12
+ * @template E
13
+ */
2
14
  export class DoublyLinkedListNode extends LinkedListNode {
3
15
  /**
4
- * The constructor function initializes the value, next, and previous properties of an object.
5
- * @param {E} value - The "value" parameter is the value that will be stored in the node. It can be of any data type, as it
6
- * is defined as a generic type "E".
16
+ * Create a node.
17
+ * @remarks Time O(1), Space O(1)
18
+ * @param value - Element value to store.
19
+ * @returns New node instance.
7
20
  */
8
21
  constructor(value) {
9
22
  super(value);
@@ -12,21 +25,47 @@ export class DoublyLinkedListNode extends LinkedListNode {
12
25
  this._prev = undefined;
13
26
  }
14
27
  _next;
28
+ /**
29
+ * Get the next node link.
30
+ * @remarks Time O(1), Space O(1)
31
+ * @returns Next node or undefined.
32
+ */
15
33
  get next() {
16
34
  return this._next;
17
35
  }
36
+ /**
37
+ * Set the next node link.
38
+ * @remarks Time O(1), Space O(1)
39
+ * @param value - Next node or undefined.
40
+ * @returns void
41
+ */
18
42
  set next(value) {
19
43
  this._next = value;
20
44
  }
21
45
  _prev;
46
+ /**
47
+ * Get the previous node link.
48
+ * @remarks Time O(1), Space O(1)
49
+ * @returns Previous node or undefined.
50
+ */
22
51
  get prev() {
23
52
  return this._prev;
24
53
  }
54
+ /**
55
+ * Set the previous node link.
56
+ * @remarks Time O(1), Space O(1)
57
+ * @param value - Previous node or undefined.
58
+ * @returns void
59
+ */
25
60
  set prev(value) {
26
61
  this._prev = value;
27
62
  }
28
63
  }
29
64
  /**
65
+ * Doubly linked list with O(1) push/pop/unshift/shift and linear scans.
66
+ * @remarks Time O(1), Space O(1)
67
+ * @template E
68
+ * @template R
30
69
  * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.
31
70
  * 2. Bidirectional Traversal: Unlike singly linked lists, doubly linked lists can be easily traversed forwards or backwards. This makes insertions and deletions in the list more flexible and efficient.
32
71
  * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.
@@ -201,6 +240,16 @@ export class DoublyLinkedListNode extends LinkedListNode {
201
240
  * this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();
202
241
  * }
203
242
  *
243
+ * // Get the current cache length
244
+ * get length(): number {
245
+ * return this.list.length;
246
+ * }
247
+ *
248
+ * // Check if it is empty
249
+ * get isEmpty(): boolean {
250
+ * return this.list.isEmpty();
251
+ * }
252
+ *
204
253
  * // Get cached value
205
254
  * get(key: K): V | undefined {
206
255
  * const node = this.map.get(key);
@@ -246,12 +295,6 @@ export class DoublyLinkedListNode extends LinkedListNode {
246
295
  * }
247
296
  * }
248
297
  *
249
- * // Move the node to the head of the linked list
250
- * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
251
- * this.list.delete(node);
252
- * this.list.unshift(node.value);
253
- * }
254
- *
255
298
  * // Delete specific key
256
299
  * delete(key: K): boolean {
257
300
  * const node = this.map.get(key);
@@ -271,14 +314,10 @@ export class DoublyLinkedListNode extends LinkedListNode {
271
314
  * this.map.clear();
272
315
  * }
273
316
  *
274
- * // Get the current cache length
275
- * get length(): number {
276
- * return this.list.length;
277
- * }
278
- *
279
- * // Check if it is empty
280
- * get isEmpty(): boolean {
281
- * return this.list.isEmpty();
317
+ * // Move the node to the head of the linked list
318
+ * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
319
+ * this.list.delete(node);
320
+ * this.list.unshift(node.value);
282
321
  * }
283
322
  * }
284
323
  *
@@ -460,97 +499,93 @@ export class DoublyLinkedListNode extends LinkedListNode {
460
499
  * console.log(scheduler.listProcesses()); // []
461
500
  */
462
501
  export class DoublyLinkedList extends LinearLinkedBase {
502
+ _equals = Object.is;
463
503
  /**
464
- * This TypeScript constructor initializes a DoublyLinkedList with optional elements and options.
465
- * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the constructor is an
466
- * iterable collection of elements of type `E` or `R`. It is used to initialize the DoublyLinkedList
467
- * with the elements provided in the iterable. If no elements are provided, the default value is an
468
- * empty iterable.
469
- * @param [options] - The `options` parameter in the constructor is of type
470
- * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
471
- * configuration options to customize the behavior of the DoublyLinkedList.
504
+ * Create a DoublyLinkedList and optionally bulk-insert elements.
505
+ * @remarks Time O(N), Space O(N)
506
+ * @param [elements] - Iterable of elements or nodes (or raw records if toElementFn is provided).
507
+ * @param [options] - Options such as maxLen and toElementFn.
508
+ * @returns New DoublyLinkedList instance.
472
509
  */
473
510
  constructor(elements = [], options) {
474
511
  super(options);
475
512
  this._head = undefined;
476
513
  this._tail = undefined;
477
514
  this._length = 0;
478
- if (options) {
479
- const { maxLen } = options;
480
- if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0)
481
- this._maxLen = maxLen;
515
+ if (options?.maxLen && Number.isInteger(options.maxLen) && options.maxLen > 0) {
516
+ this._maxLen = options.maxLen;
482
517
  }
483
518
  this.pushMany(elements);
484
519
  }
485
520
  _head;
521
+ /**
522
+ * Get the head node.
523
+ * @remarks Time O(1), Space O(1)
524
+ * @returns Head node or undefined.
525
+ */
486
526
  get head() {
487
527
  return this._head;
488
528
  }
489
529
  _tail;
530
+ /**
531
+ * Get the tail node.
532
+ * @remarks Time O(1), Space O(1)
533
+ * @returns Tail node or undefined.
534
+ */
490
535
  get tail() {
491
536
  return this._tail;
492
537
  }
493
- _length;
538
+ _length = 0;
539
+ /**
540
+ * Get the number of elements.
541
+ * @remarks Time O(1), Space O(1)
542
+ * @returns Current length.
543
+ */
494
544
  get length() {
495
545
  return this._length;
496
546
  }
497
547
  /**
498
- * Time Complexity: O(1)
499
- * Space Complexity: O(1)
500
- *
501
- * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.
502
- * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.
548
+ * Get the first element value.
549
+ * @remarks Time O(1), Space O(1)
550
+ * @returns First element or undefined.
503
551
  */
504
552
  get first() {
505
553
  return this.head?.value;
506
554
  }
507
555
  /**
508
- * Time Complexity: O(1)
509
- * Space Complexity: O(1)
510
- *
511
- * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.
512
- * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.
556
+ * Get the last element value.
557
+ * @remarks Time O(1), Space O(1)
558
+ * @returns Last element or undefined.
513
559
  */
514
560
  get last() {
515
561
  return this.tail?.value;
516
562
  }
517
563
  /**
518
- * Time Complexity: O(n)
519
- * Space Complexity: O(n)
520
- *
521
- * The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the
522
- * given array.
523
- * @param {E[]} data - The `data` parameter is an array of elements of type `E`.
524
- * @returns The `fromArray` function returns a DoublyLinkedList object.
564
+ * Create a new list from an array of elements.
565
+ * @remarks Time O(N), Space O(N)
566
+ * @template E
567
+ * @template R
568
+ * @param this - The constructor (subclass) to instantiate.
569
+ * @param data - Array of elements to insert.
570
+ * @returns A new list populated with the array's elements.
525
571
  */
526
572
  static fromArray(data) {
527
- return new DoublyLinkedList(data);
573
+ return new this(data);
528
574
  }
529
575
  /**
530
- * Time Complexity: O(1)
531
- * Space Complexity: O(1)
532
- *
533
- * The function `isNode` in TypeScript checks if a given input is an instance of
534
- * `DoublyLinkedListNode`.
535
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
536
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can
537
- * be one of the following types:
538
- * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
539
- * instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
540
- * parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,
541
- * the function returns `false`.
576
+ * Type guard: check whether the input is a DoublyLinkedListNode.
577
+ * @remarks Time O(1), Space O(1)
578
+ * @param elementNodeOrPredicate - Element, node, or predicate.
579
+ * @returns True if the value is a DoublyLinkedListNode.
542
580
  */
543
581
  isNode(elementNodeOrPredicate) {
544
582
  return elementNodeOrPredicate instanceof DoublyLinkedListNode;
545
583
  }
546
584
  /**
547
- * Time Complexity: O(1)
548
- * Space Complexity: O(1)
549
- *
550
- * The `push` function adds a new element or node to the end of a doubly linked list.
551
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
552
- * method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.
553
- * @returns The `push` method is returning a boolean value, specifically `true`.
585
+ * Append an element/node to the tail.
586
+ * @remarks Time O(1), Space O(1)
587
+ * @param elementOrNode - Element or node to append.
588
+ * @returns True when appended.
554
589
  */
555
590
  push(elementOrNode) {
556
591
  const newNode = this._ensureNode(elementOrNode);
@@ -569,58 +604,50 @@ export class DoublyLinkedList extends LinearLinkedBase {
569
604
  return true;
570
605
  }
571
606
  /**
572
- * Time Complexity: O(1)
573
- * Space Complexity: O(1)
574
- *
575
- * The `pop()` function removes and returns the value of the last element in a linked list.
576
- * @returns The method is returning the value of the removed node.
607
+ * Remove and return the tail element.
608
+ * @remarks Time O(1), Space O(1)
609
+ * @returns Removed element or undefined.
577
610
  */
578
611
  pop() {
579
612
  if (!this.tail)
580
613
  return undefined;
581
- const removedNode = this.tail;
614
+ const removed = this.tail;
582
615
  if (this.head === this.tail) {
583
616
  this._head = undefined;
584
617
  this._tail = undefined;
585
618
  }
586
619
  else {
587
- this._tail = removedNode.prev;
620
+ this._tail = removed.prev;
588
621
  this.tail.next = undefined;
589
622
  }
590
623
  this._length--;
591
- return removedNode.value;
624
+ return removed.value;
592
625
  }
593
626
  /**
594
- * Time Complexity: O(1)
595
- * Space Complexity: O(1)
596
- *
597
- * The `shift()` function removes and returns the value of the first element in a doubly linked list.
598
- * @returns The value of the removed node.
627
+ * Remove and return the head element.
628
+ * @remarks Time O(1), Space O(1)
629
+ * @returns Removed element or undefined.
599
630
  */
600
631
  shift() {
601
632
  if (!this.head)
602
633
  return undefined;
603
- const removedNode = this.head;
634
+ const removed = this.head;
604
635
  if (this.head === this.tail) {
605
636
  this._head = undefined;
606
637
  this._tail = undefined;
607
638
  }
608
639
  else {
609
- this._head = removedNode.next;
640
+ this._head = removed.next;
610
641
  this.head.prev = undefined;
611
642
  }
612
643
  this._length--;
613
- return removedNode.value;
644
+ return removed.value;
614
645
  }
615
646
  /**
616
- * Time Complexity: O(1)
617
- * Space Complexity: O(1)
618
- *
619
- * The unshift function adds a new element or node to the beginning of a doubly linked list.
620
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
621
- * `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
622
- * element of type `E`.
623
- * @returns The `unshift` method is returning a boolean value, specifically `true`.
647
+ * Prepend an element/node to the head.
648
+ * @remarks Time O(1), Space O(1)
649
+ * @param elementOrNode - Element or node to prepend.
650
+ * @returns True when prepended.
624
651
  */
625
652
  unshift(elementOrNode) {
626
653
  const newNode = this._ensureNode(elementOrNode);
@@ -639,151 +666,114 @@ export class DoublyLinkedList extends LinearLinkedBase {
639
666
  return true;
640
667
  }
641
668
  /**
642
- * Time Complexity: O(k)
643
- * Space Complexity: O(k)
644
- *
645
- * The function `pushMany` iterates over elements and pushes them into a data structure, applying a
646
- * transformation function if provided.
647
- * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
648
- * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,
649
- * or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes
650
- * it onto the linked list. If a transformation function `to
651
- * @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate
652
- * the success or failure of pushing each element into the data structure.
669
+ * Append a sequence of elements/nodes.
670
+ * @remarks Time O(N), Space O(1)
671
+ * @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
672
+ * @returns Array of per-element success flags.
653
673
  */
654
674
  pushMany(elements) {
655
675
  const ans = [];
656
676
  for (const el of elements) {
657
- if (this.toElementFn) {
677
+ if (this.toElementFn)
658
678
  ans.push(this.push(this.toElementFn(el)));
659
- continue;
660
- }
661
- ans.push(this.push(el));
679
+ else
680
+ ans.push(this.push(el));
662
681
  }
663
682
  return ans;
664
683
  }
665
684
  /**
666
- * Time Complexity: O(k)
667
- * Space Complexity: O(k)
668
- *
669
- * The function `unshiftMany` iterates through a collection of elements and adds them to the
670
- * beginning of a Doubly Linked List, returning an array of boolean values indicating the success of
671
- * each insertion.
672
- * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
673
- * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,
674
- * `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and
675
- * performs an `unshift` operation on the doubly linked list
676
- * @returns The `unshiftMany` function returns an array of boolean values indicating the success of
677
- * each unshift operation performed on the elements passed as input.
685
+ * Prepend a sequence of elements/nodes.
686
+ * @remarks Time O(N), Space O(1)
687
+ * @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
688
+ * @returns Array of per-element success flags.
678
689
  */
679
690
  unshiftMany(elements) {
680
691
  const ans = [];
681
692
  for (const el of elements) {
682
- if (this.toElementFn) {
693
+ if (this.toElementFn)
683
694
  ans.push(this.unshift(this.toElementFn(el)));
684
- continue;
685
- }
686
- ans.push(this.unshift(el));
695
+ else
696
+ ans.push(this.unshift(el));
687
697
  }
688
698
  return ans;
689
699
  }
690
700
  /**
691
- * Time Complexity: O(n)
692
- * Space Complexity: O(1)
693
- *
694
- * The `at` function returns the value at a specified index in a linked list, or undefined if the index is out of bounds.
695
- * @param {number} index - The index parameter is a number that represents the position of the element we want to
696
- * retrieve from the list.
697
- * @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds
698
- * or the linked list is empty, it will return undefined.
701
+ * Get the element at a given index.
702
+ * @remarks Time O(N), Space O(1)
703
+ * @param index - Zero-based index.
704
+ * @returns Element or undefined.
699
705
  */
700
706
  at(index) {
701
707
  if (index < 0 || index >= this._length)
702
708
  return undefined;
703
709
  let current = this.head;
704
- for (let i = 0; i < index; i++) {
710
+ for (let i = 0; i < index; i++)
705
711
  current = current.next;
706
- }
707
712
  return current.value;
708
713
  }
709
714
  /**
710
- * Time Complexity: O(n)
711
- * Space Complexity: O(1)
712
- *
713
- * The function `getNodeAt` returns the node at a given index in a doubly linked list, or undefined if the index is out of
714
- * range.
715
- * @param {number} index - The `index` parameter is a number that represents the position of the node we want to
716
- * retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.
717
- * @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the
718
- * valid range of the linked list, otherwise it returns `undefined`.
715
+ * Get the node reference at a given index.
716
+ * @remarks Time O(N), Space O(1)
717
+ * @param index - Zero-based index.
718
+ * @returns Node or undefined.
719
719
  */
720
720
  getNodeAt(index) {
721
721
  if (index < 0 || index >= this._length)
722
722
  return undefined;
723
723
  let current = this.head;
724
- for (let i = 0; i < index; i++) {
724
+ for (let i = 0; i < index; i++)
725
725
  current = current.next;
726
- }
727
726
  return current;
728
727
  }
729
728
  /**
730
- * Time Complexity: O(n)
731
- * Space Complexity: O(1)
732
- *
733
- * This TypeScript function searches for a node in a doubly linked list based on a given element node
734
- * or predicate.
735
- * @param {| E
736
- * | DoublyLinkedListNode<E>
737
- * | ((node: DoublyLinkedListNode<E>) => boolean)
738
- * | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a
739
- * node in a doubly linked list based on a given element, node, or predicate function. The
740
- * `elementNodeOrPredicate` parameter can be one of the following:
741
- * @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the
742
- * input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.
743
- * Otherwise, it iterates through the linked list starting from the head node and applies the
744
- * provided predicate function to each node. If a node satisfies the predicate, that node is
745
- * returned. If
729
+ * Find a node by value, reference, or predicate.
730
+ * @remarks Time O(N), Space O(1)
731
+ * @param [elementNodeOrPredicate] - Element, node, or predicate to match.
732
+ * @returns Matching node or undefined.
746
733
  */
747
734
  getNode(elementNodeOrPredicate) {
748
735
  if (elementNodeOrPredicate === undefined)
749
736
  return;
750
- if (this.isNode(elementNodeOrPredicate))
751
- return elementNodeOrPredicate;
737
+ if (this.isNode(elementNodeOrPredicate)) {
738
+ const target = elementNodeOrPredicate;
739
+ let cur = this.head;
740
+ while (cur) {
741
+ if (cur === target)
742
+ return target;
743
+ cur = cur.next;
744
+ }
745
+ const isMatch = (node) => this._equals(node.value, target.value);
746
+ cur = this.head;
747
+ while (cur) {
748
+ if (isMatch(cur))
749
+ return cur;
750
+ cur = cur.next;
751
+ }
752
+ return undefined;
753
+ }
752
754
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
753
755
  let current = this.head;
754
756
  while (current) {
755
- if (predicate(current)) {
757
+ if (predicate(current))
756
758
  return current;
757
- }
758
759
  current = current.next;
759
760
  }
760
761
  return undefined;
761
762
  }
762
763
  /**
763
- * Time Complexity: O(n)
764
- * Space Complexity: O(1)
765
- *
766
- * The `addAt` function inserts a new element or node at a specified index in a doubly linked list.
767
- * @param {number} index - The `index` parameter in the `addAt` method represents the position at
768
- * which you want to add a new element or node in the doubly linked list. It indicates the location
769
- * where the new element or node should be inserted.
770
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
771
- * `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.
772
- * @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was
773
- * successfully added at the specified index, and `false` if the index is out of bounds (less than 0
774
- * or greater than the length of the list).
764
+ * Insert a new element/node at an index, shifting following nodes.
765
+ * @remarks Time O(N), Space O(1)
766
+ * @param index - Zero-based index.
767
+ * @param newElementOrNode - Element or node to insert.
768
+ * @returns True if inserted.
775
769
  */
776
770
  addAt(index, newElementOrNode) {
777
771
  if (index < 0 || index > this._length)
778
772
  return false;
779
- if (index === 0) {
780
- this.unshift(newElementOrNode);
781
- return true;
782
- }
783
- if (index === this._length) {
784
- this.push(newElementOrNode);
785
- return true;
786
- }
773
+ if (index === 0)
774
+ return this.unshift(newElementOrNode);
775
+ if (index === this._length)
776
+ return this.push(newElementOrNode);
787
777
  const newNode = this._ensureNode(newElementOrNode);
788
778
  const prevNode = this.getNodeAt(index - 1);
789
779
  const nextNode = prevNode.next;
@@ -795,179 +785,123 @@ export class DoublyLinkedList extends LinearLinkedBase {
795
785
  return true;
796
786
  }
797
787
  /**
798
- * Time Complexity: O(1) or O(n)
799
- * Space Complexity: O(1)
800
- *
801
- * The `addBefore` function in TypeScript adds a new element or node before an existing element or
802
- * node in a doubly linked list.
803
- * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter
804
- * in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.
805
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter
806
- * represents the element or node that you want to add before the `existingElementOrNode` in a doubly
807
- * linked list.
808
- * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
809
- * successfully added before the existing element or node, and `false` if the existing element or
810
- * node was not found.
788
+ * Insert a new element/node before an existing one.
789
+ * @remarks Time O(N), Space O(1)
790
+ * @param existingElementOrNode - Existing element or node.
791
+ * @param newElementOrNode - Element or node to insert.
792
+ * @returns True if inserted.
811
793
  */
812
794
  addBefore(existingElementOrNode, newElementOrNode) {
813
795
  const existingNode = this.isNode(existingElementOrNode)
814
796
  ? existingElementOrNode
815
797
  : this.getNode(existingElementOrNode);
816
- if (existingNode) {
817
- const newNode = this._ensureNode(newElementOrNode);
818
- newNode.prev = existingNode.prev;
819
- if (existingNode.prev) {
820
- existingNode.prev.next = newNode;
821
- }
822
- newNode.next = existingNode;
823
- existingNode.prev = newNode;
824
- if (existingNode === this.head) {
825
- this._head = newNode;
826
- }
827
- this._length++;
828
- return true;
829
- }
830
- return false;
798
+ if (!existingNode)
799
+ return false;
800
+ const newNode = this._ensureNode(newElementOrNode);
801
+ newNode.prev = existingNode.prev;
802
+ if (existingNode.prev)
803
+ existingNode.prev.next = newNode;
804
+ newNode.next = existingNode;
805
+ existingNode.prev = newNode;
806
+ if (existingNode === this.head)
807
+ this._head = newNode;
808
+ this._length++;
809
+ return true;
831
810
  }
832
811
  /**
833
- * Time Complexity: O(1) or O(n)
834
- * Space Complexity: O(1)
835
- *
836
- * The `addAfter` function in TypeScript adds a new element or node after an existing element or node
837
- * in a doubly linked list.
838
- * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
839
- * element or node in the doubly linked list after which you want to add a new element or node.
840
- * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
841
- * `addAfter` method represents the element or node that you want to add after the existing element
842
- * or node in a doubly linked list. This parameter can be either an element value or a
843
- * `DoublyLinkedListNode` object that you want to insert
844
- * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
845
- * successfully added after the existing element or node, and `false` if the existing element or node
846
- * was not found in the linked list.
812
+ * Insert a new element/node after an existing one.
813
+ * @remarks Time O(N), Space O(1)
814
+ * @param existingElementOrNode - Existing element or node.
815
+ * @param newElementOrNode - Element or node to insert.
816
+ * @returns True if inserted.
847
817
  */
848
818
  addAfter(existingElementOrNode, newElementOrNode) {
849
819
  const existingNode = this.isNode(existingElementOrNode)
850
820
  ? existingElementOrNode
851
821
  : this.getNode(existingElementOrNode);
852
- if (existingNode) {
853
- const newNode = this._ensureNode(newElementOrNode);
854
- newNode.next = existingNode.next;
855
- if (existingNode.next) {
856
- existingNode.next.prev = newNode;
857
- }
858
- newNode.prev = existingNode;
859
- existingNode.next = newNode;
860
- if (existingNode === this.tail) {
861
- this._tail = newNode;
862
- }
863
- this._length++;
864
- return true;
865
- }
866
- return false;
822
+ if (!existingNode)
823
+ return false;
824
+ const newNode = this._ensureNode(newElementOrNode);
825
+ newNode.next = existingNode.next;
826
+ if (existingNode.next)
827
+ existingNode.next.prev = newNode;
828
+ newNode.prev = existingNode;
829
+ existingNode.next = newNode;
830
+ if (existingNode === this.tail)
831
+ this._tail = newNode;
832
+ this._length++;
833
+ return true;
867
834
  }
868
835
  /**
869
- * Time Complexity: O(n)
870
- * Space Complexity: O(1)
871
- *
872
- * The function `setAt` updates the value at a specified index in a data structure if the index
873
- * exists.
874
- * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
875
- * data structure where you want to set a new value.
876
- * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
877
- * want to set at the specified index in the data structure.
878
- * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
879
- * is successfully updated, and `false` if the index is out of bounds.
836
+ * Set the element value at an index.
837
+ * @remarks Time O(N), Space O(1)
838
+ * @param index - Zero-based index.
839
+ * @param value - New value.
840
+ * @returns True if updated.
880
841
  */
881
842
  setAt(index, value) {
882
843
  const node = this.getNodeAt(index);
883
- if (node) {
884
- node.value = value;
885
- return true;
886
- }
887
- return false;
844
+ if (!node)
845
+ return false;
846
+ node.value = value;
847
+ return true;
888
848
  }
889
849
  /**
890
- * Time Complexity: O(n)
891
- * Space Complexity: O(1)
892
- *
893
- * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.
894
- * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the
895
- * data structure. It is of type number.
896
- * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
897
- * bounds.
850
+ * Delete the element at an index.
851
+ * @remarks Time O(N), Space O(1)
852
+ * @param index - Zero-based index.
853
+ * @returns Removed element or undefined.
898
854
  */
899
855
  deleteAt(index) {
900
856
  if (index < 0 || index >= this._length)
901
857
  return;
902
- let deleted;
903
- if (index === 0) {
904
- deleted = this.first;
905
- this.shift();
906
- return deleted;
907
- }
908
- if (index === this._length - 1) {
909
- deleted = this.last;
910
- this.pop();
911
- return deleted;
912
- }
858
+ if (index === 0)
859
+ return this.shift();
860
+ if (index === this._length - 1)
861
+ return this.pop();
913
862
  const removedNode = this.getNodeAt(index);
914
863
  const prevNode = removedNode.prev;
915
864
  const nextNode = removedNode.next;
916
865
  prevNode.next = nextNode;
917
866
  nextNode.prev = prevNode;
918
867
  this._length--;
919
- return removedNode?.value;
868
+ return removedNode.value;
920
869
  }
921
870
  /**
922
- * Time Complexity: O(1) or O(n)
923
- * Space Complexity: O(1)
924
- *
925
- * The `delete` function removes a specified element or node from a doubly linked list if it exists.
926
- * @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in
927
- * the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it
928
- * can be `undefined`. This parameter is used to identify the node that needs to be deleted from the
929
- * doubly linked list
930
- * @returns The `delete` method returns a boolean value - `true` if the element or node was
931
- * successfully deleted from the doubly linked list, and `false` if the element or node was not found
932
- * in the list.
871
+ * Delete the first match by value/node.
872
+ * @remarks Time O(N), Space O(1)
873
+ * @param [elementOrNode] - Element or node to remove.
874
+ * @returns True if removed.
933
875
  */
934
876
  delete(elementOrNode) {
935
877
  const node = this.getNode(elementOrNode);
936
- if (node) {
937
- if (node === this.head) {
938
- this.shift();
939
- }
940
- else if (node === this.tail) {
941
- this.pop();
942
- }
943
- else {
944
- const prevNode = node.prev;
945
- const nextNode = node.next;
946
- if (prevNode)
947
- prevNode.next = nextNode;
948
- if (nextNode)
949
- nextNode.prev = prevNode;
950
- this._length--;
951
- }
952
- return true;
878
+ if (!node)
879
+ return false;
880
+ if (node === this.head)
881
+ this.shift();
882
+ else if (node === this.tail)
883
+ this.pop();
884
+ else {
885
+ const prevNode = node.prev;
886
+ const nextNode = node.next;
887
+ prevNode.next = nextNode;
888
+ nextNode.prev = prevNode;
889
+ this._length--;
953
890
  }
954
- return false;
891
+ return true;
955
892
  }
956
893
  /**
957
- * Time Complexity: O(1)
958
- * Space Complexity: O(1)
959
- *
960
- * The function checks if a variable has a length greater than zero and returns a boolean value.
961
- * @returns A boolean value is being returned.
894
+ * Check whether the list is empty.
895
+ * @remarks Time O(1), Space O(1)
896
+ * @returns True if length is 0.
962
897
  */
963
898
  isEmpty() {
964
899
  return this._length === 0;
965
900
  }
966
901
  /**
967
- * Time Complexity: O(1)
968
- * Space Complexity: O(1)
969
- *
970
- * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.
902
+ * Remove all nodes and reset length.
903
+ * @remarks Time O(N), Space O(1)
904
+ * @returns void
971
905
  */
972
906
  clear() {
973
907
  this._head = undefined;
@@ -975,16 +909,10 @@ export class DoublyLinkedList extends LinearLinkedBase {
975
909
  this._length = 0;
976
910
  }
977
911
  /**
978
- * Time Complexity: O(n)
979
- * Space Complexity: O(1)
980
- *
981
- * This function retrieves an element from a doubly linked list based on a given element
982
- * node or predicate.
983
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
984
- * elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,
985
- * which can be one of the following types:
986
- * @returns The `get` method returns the value of the first node in the doubly linked list that
987
- * satisfies the provided predicate function. If no such node is found, it returns `undefined`.
912
+ * Find the first value matching a predicate scanning forward.
913
+ * @remarks Time O(N), Space O(1)
914
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
915
+ * @returns Matched value or undefined.
988
916
  */
989
917
  search(elementNodeOrPredicate) {
990
918
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
@@ -997,17 +925,10 @@ export class DoublyLinkedList extends LinearLinkedBase {
997
925
  return undefined;
998
926
  }
999
927
  /**
1000
- * Time Complexity: O(n)
1001
- * Space Complexity: O(1)
1002
- *
1003
- * The `getBackward` function searches for a specific element in a doubly linked list starting from
1004
- * the tail and moving backwards.
1005
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1006
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`
1007
- * function can be one of the following types:
1008
- * @returns The `getBackward` method returns the value of the element node that matches the provided
1009
- * predicate when traversing the doubly linked list backwards. If no matching element is found, it
1010
- * returns `undefined`.
928
+ * Find the first value matching a predicate scanning backward.
929
+ * @remarks Time O(N), Space O(1)
930
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
931
+ * @returns Matched value or undefined.
1011
932
  */
1012
933
  getBackward(elementNodeOrPredicate) {
1013
934
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
@@ -1020,10 +941,9 @@ export class DoublyLinkedList extends LinearLinkedBase {
1020
941
  return undefined;
1021
942
  }
1022
943
  /**
1023
- * Time Complexity: O(n)
1024
- * Space Complexity: O(1)
1025
- *
1026
- * The `reverse` function reverses the order of the elements in a doubly linked list.
944
+ * Reverse the list in place.
945
+ * @remarks Time O(N), Space O(1)
946
+ * @returns This list.
1027
947
  */
1028
948
  reverse() {
1029
949
  let current = this.head;
@@ -1036,100 +956,134 @@ export class DoublyLinkedList extends LinearLinkedBase {
1036
956
  return this;
1037
957
  }
1038
958
  /**
1039
- * Time Complexity: O(n)
1040
- * Space Complexity: O(n)
1041
- *
1042
- * The `clone` function creates a new instance of the `DoublyLinkedList` class with the same values
1043
- * as the original list.
1044
- * @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which
1045
- * is a copy of the original list.
959
+ * Set the equality comparator used to compare values.
960
+ * @remarks Time O(1), Space O(1)
961
+ * @param equals - Equality predicate (a, b) → boolean.
962
+ * @returns This list.
963
+ */
964
+ setEquality(equals) {
965
+ this._equals = equals;
966
+ return this;
967
+ }
968
+ /**
969
+ * Deep clone this list (values are copied by reference).
970
+ * @remarks Time O(N), Space O(N)
971
+ * @returns A new list with the same element sequence.
1046
972
  */
1047
973
  clone() {
1048
- return new DoublyLinkedList(this, { toElementFn: this._toElementFn, maxLen: this._maxLen });
974
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
975
+ for (const v of this)
976
+ out.push(v);
977
+ return out;
1049
978
  }
1050
979
  /**
1051
- * Time Complexity: O(n)
1052
- * Space Complexity: O(n)
1053
- *
1054
- * The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current
1055
- * list and applying a callback function to each element, returning only the elements for which the
1056
- * callback function returns true.
1057
- * @param callback - The `callback` parameter is a function that will be called for each element in
1058
- * the DoublyLinkedList. It takes three arguments: the current element, the index of the current
1059
- * element, and the DoublyLinkedList itself. The callback function should return a boolean value
1060
- * indicating whether the current element should be included
1061
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
1062
- * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
1063
- * passed as the `this` value to the `callback` function. If `thisArg` is
1064
- * @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
1065
- * elements that pass the filter condition specified by the `callback` function.
980
+ * Filter values into a new list of the same class.
981
+ * @remarks Time O(N), Space O(N)
982
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
983
+ * @param [thisArg] - Value for `this` inside the callback.
984
+ * @returns A new list with kept values.
1066
985
  */
1067
986
  filter(callback, thisArg) {
1068
- const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
987
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1069
988
  let index = 0;
1070
- for (const current of this) {
1071
- if (callback.call(thisArg, current, index, this)) {
1072
- filteredList.push(current);
1073
- }
1074
- index++;
1075
- }
1076
- return filteredList;
989
+ for (const v of this)
990
+ if (callback.call(thisArg, v, index++, this))
991
+ out.push(v);
992
+ return out;
1077
993
  }
1078
994
  /**
1079
- * Time Complexity: O(n)
1080
- * Space Complexity: O(n)
1081
- *
1082
- * The `map` function takes a callback function and returns a new DoublyLinkedList with the results
1083
- * of applying the callback to each element in the original list.
1084
- * @param callback - The callback parameter is a function that will be called for each element in the
1085
- * original DoublyLinkedList. It takes three arguments: current (the current element being
1086
- * processed), index (the index of the current element), and this (the original DoublyLinkedList).
1087
- * The callback function should return a value of type
1088
- * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
1089
- * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as
1090
- * input and returns the converted element. If this parameter is not provided, the raw element will
1091
- * be used as is.
1092
- * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
1093
- * specify the value of `this` within the callback function. It is used to set the context or scope
1094
- * in which the callback function will be executed. If `thisArg` is provided, it will be used as the
1095
- * value of
1096
- * @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
995
+ * Map values into a new list of the same class.
996
+ * @remarks Time O(N), Space O(N)
997
+ * @param callback - Mapping function (value, index, list) → newValue.
998
+ * @param [thisArg] - Value for `this` inside the callback.
999
+ * @returns A new list with mapped values.
1097
1000
  */
1098
- map(callback, toElementFn, thisArg) {
1099
- const mappedList = new DoublyLinkedList([], { toElementFn, maxLen: this._maxLen });
1001
+ mapSame(callback, thisArg) {
1002
+ const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1100
1003
  let index = 0;
1101
- for (const current of this) {
1102
- mappedList.push(callback.call(thisArg, current, index, this));
1103
- index++;
1004
+ for (const v of this) {
1005
+ const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
1006
+ out.push(mv);
1104
1007
  }
1105
- return mappedList;
1008
+ return out;
1106
1009
  }
1107
1010
  /**
1108
- * Time Complexity: O(n)
1109
- * Space Complexity: O(1)
1110
- *
1111
- * The function `countOccurrences` iterates through a doubly linked list and counts the occurrences
1112
- * of a specified element or nodes that satisfy a given predicate.
1113
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementOrNode
1114
- * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:
1115
- * @returns The `countOccurrences` method returns the number of occurrences of the specified element,
1116
- * node, or predicate function in the doubly linked list.
1011
+ * Map values into a new list (possibly different element type).
1012
+ * @remarks Time O(N), Space O(N)
1013
+ * @template EM
1014
+ * @template RM
1015
+ * @param callback - Mapping function (value, index, list) newElement.
1016
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1017
+ * @param [thisArg] - Value for `this` inside the callback.
1018
+ * @returns A new DoublyLinkedList with mapped values.
1117
1019
  */
1118
- countOccurrences(elementOrNode) {
1119
- const predicate = this._ensurePredicate(elementOrNode);
1120
- let count = 0;
1121
- let current = this.head;
1122
- while (current) {
1123
- if (predicate(current)) {
1124
- count++;
1125
- }
1126
- current = current.next;
1020
+ map(callback, options, thisArg) {
1021
+ const out = this._createLike([], { ...(options ?? {}), maxLen: this._maxLen });
1022
+ let index = 0;
1023
+ for (const v of this)
1024
+ out.push(callback.call(thisArg, v, index++, this));
1025
+ return out;
1026
+ }
1027
+ /**
1028
+ * (Protected) Create or return a node for the given input (node or raw element).
1029
+ * @remarks Time O(1), Space O(1)
1030
+ * @param elementOrNode - Element value or node to normalize.
1031
+ * @returns A DoublyLinkedListNode for the provided input.
1032
+ */
1033
+ _ensureNode(elementOrNode) {
1034
+ if (this.isNode(elementOrNode))
1035
+ return elementOrNode;
1036
+ return new DoublyLinkedListNode(elementOrNode);
1037
+ }
1038
+ /**
1039
+ * (Protected) Normalize input into a predicate over nodes.
1040
+ * @remarks Time O(1), Space O(1)
1041
+ * @param elementNodeOrPredicate - Element, node, or node predicate.
1042
+ * @returns A predicate function taking a node and returning true/false.
1043
+ */
1044
+ _ensurePredicate(elementNodeOrPredicate) {
1045
+ if (this.isNode(elementNodeOrPredicate)) {
1046
+ const target = elementNodeOrPredicate;
1047
+ return (node) => node === target;
1048
+ }
1049
+ if (typeof elementNodeOrPredicate === 'function') {
1050
+ return elementNodeOrPredicate;
1127
1051
  }
1128
- return count;
1052
+ const value = elementNodeOrPredicate;
1053
+ return (node) => this._equals(node.value, value);
1054
+ }
1055
+ /**
1056
+ * (Protected) Get the previous node of a given node.
1057
+ * @remarks Time O(1), Space O(1)
1058
+ * @param node - A node in the list.
1059
+ * @returns Previous node or undefined.
1060
+ */
1061
+ _getPrevNode(node) {
1062
+ return node.prev;
1063
+ }
1064
+ /**
1065
+ * (Protected) Create an empty instance of the same concrete class.
1066
+ * @remarks Time O(1), Space O(1)
1067
+ * @param [options] - Options forwarded to the constructor.
1068
+ * @returns An empty like-kind list instance.
1069
+ */
1070
+ _createInstance(options) {
1071
+ const Ctor = this.constructor;
1072
+ return new Ctor([], options);
1129
1073
  }
1130
1074
  /**
1131
- * The function returns an iterator that iterates over the values of a linked list.
1075
+ * (Protected) Create a like-kind instance and seed it from an iterable.
1076
+ * @remarks Time O(N), Space O(N)
1077
+ * @template EM
1078
+ * @template RM
1079
+ * @param [elements] - Iterable used to seed the new list.
1080
+ * @param [options] - Options forwarded to the constructor.
1081
+ * @returns A like-kind DoublyLinkedList instance.
1132
1082
  */
1083
+ _createLike(elements = [], options) {
1084
+ const Ctor = this.constructor;
1085
+ return new Ctor(elements, options);
1086
+ }
1133
1087
  *_getIterator() {
1134
1088
  let current = this.head;
1135
1089
  while (current) {
@@ -1137,10 +1091,6 @@ export class DoublyLinkedList extends LinearLinkedBase {
1137
1091
  current = current.next;
1138
1092
  }
1139
1093
  }
1140
- /**
1141
- * The function returns an iterator that iterates over the elements of a data structure in reverse
1142
- * order.
1143
- */
1144
1094
  *_getReverseIterator() {
1145
1095
  let current = this.tail;
1146
1096
  while (current) {
@@ -1148,10 +1098,6 @@ export class DoublyLinkedList extends LinearLinkedBase {
1148
1098
  current = current.prev;
1149
1099
  }
1150
1100
  }
1151
- /**
1152
- * The function returns an iterator that iterates over the nodes of a doubly linked list starting
1153
- * from the head.
1154
- */
1155
1101
  *_getNodeIterator() {
1156
1102
  let current = this.head;
1157
1103
  while (current) {
@@ -1159,78 +1105,5 @@ export class DoublyLinkedList extends LinearLinkedBase {
1159
1105
  current = current.next;
1160
1106
  }
1161
1107
  }
1162
- // protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
1163
- // const reversedArr = [...this._getNodeIterator()].reverse();
1164
- //
1165
- // for (const item of reversedArr) {
1166
- // yield item;
1167
- // }
1168
- // }
1169
- /**
1170
- * The function `_isPredicate` checks if the input is a function that takes a `DoublyLinkedListNode`
1171
- * as an argument and returns a boolean.
1172
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1173
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
1174
- * types:
1175
- * @returns The _isPredicate method is returning a boolean value indicating whether the
1176
- * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
1177
- * function, the method will return true, indicating that it is a predicate function.
1178
- */
1179
- _isPredicate(elementNodeOrPredicate) {
1180
- return typeof elementNodeOrPredicate === 'function';
1181
- }
1182
- /**
1183
- * The function `_ensureNode` ensures that the input is a valid node in a doubly linked list.
1184
- * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either
1185
- * an element of type `E` or a `DoublyLinkedListNode` containing an element of type `E`.
1186
- * @returns If the `elementOrNode` parameter is already a `DoublyLinkedListNode`, it will be returned
1187
- * as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`
1188
- * value and returned.
1189
- */
1190
- _ensureNode(elementOrNode) {
1191
- if (this.isNode(elementOrNode))
1192
- return elementOrNode;
1193
- return new DoublyLinkedListNode(elementOrNode);
1194
- }
1195
- /**
1196
- * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate
1197
- * function, or a value to compare with the node's value.
1198
- * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
1199
- * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
1200
- * types:
1201
- * @returns A function is being returned that takes a `DoublyLinkedListNode` as a parameter and
1202
- * returns a boolean value based on the conditions specified in the code.
1203
- */
1204
- _ensurePredicate(elementNodeOrPredicate) {
1205
- if (this.isNode(elementNodeOrPredicate))
1206
- return (node) => node === elementNodeOrPredicate;
1207
- if (this._isPredicate(elementNodeOrPredicate))
1208
- return elementNodeOrPredicate;
1209
- return (node) => node.value === elementNodeOrPredicate;
1210
- }
1211
- /**
1212
- * The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified
1213
- * options.
1214
- * @param [options] - The `options` parameter in the `_createInstance` method is of type
1215
- * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
1216
- * configuration options when creating a new instance of the `DoublyLinkedList` class.
1217
- * @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options
1218
- * is being returned, cast as the current class type.
1219
- */
1220
- _createInstance(options) {
1221
- return new DoublyLinkedList([], options);
1222
- }
1223
- /**
1224
- * The function `_getPrevNode` returns the previous node of a given node in a doubly linked list.
1225
- * @param node - The parameter `node` in the `_getPrevNode` method is of type
1226
- * `DoublyLinkedListNode<E>`, which represents a node in a doubly linked list containing an element
1227
- * of type `E`.
1228
- * @returns The `_getPrevNode` method is returning the previous node of the input `node` in a doubly
1229
- * linked list. If the input node has a previous node, it will return that node. Otherwise, it will
1230
- * return `undefined`.
1231
- */
1232
- _getPrevNode(node) {
1233
- return node.prev;
1234
- }
1235
1108
  }
1236
1109
  //# sourceMappingURL=doubly-linked-list.js.map