linked-list-typed 2.4.5 → 2.5.1

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 (94) hide show
  1. package/README.md +14 -50
  2. package/dist/cjs/index.cjs +2586 -292
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +2592 -289
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +2586 -292
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +2592 -289
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/data-structures/base/index.d.ts +1 -0
  11. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  12. package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
  13. package/dist/types/data-structures/base/linear-base.d.ts +3 -3
  14. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +380 -51
  15. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +487 -147
  16. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +956 -80
  17. package/dist/types/data-structures/binary-tree/bst.d.ts +816 -29
  18. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +610 -31
  19. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +326 -135
  20. package/dist/types/data-structures/binary-tree/tree-map.d.ts +3781 -6
  21. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3607 -201
  22. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2874 -65
  23. package/dist/types/data-structures/binary-tree/tree-set.d.ts +3528 -6
  24. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
  25. package/dist/types/data-structures/graph/directed-graph.d.ts +429 -47
  26. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  27. package/dist/types/data-structures/graph/undirected-graph.d.ts +393 -59
  28. package/dist/types/data-structures/hash/hash-map.d.ts +473 -89
  29. package/dist/types/data-structures/heap/heap.d.ts +581 -99
  30. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  31. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  32. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +646 -47
  33. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +596 -68
  34. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +793 -12
  35. package/dist/types/data-structures/matrix/matrix.d.ts +499 -0
  36. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  37. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  38. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  39. package/dist/types/data-structures/queue/deque.d.ts +593 -71
  40. package/dist/types/data-structures/queue/queue.d.ts +463 -42
  41. package/dist/types/data-structures/stack/stack.d.ts +384 -32
  42. package/dist/types/data-structures/trie/trie.d.ts +470 -48
  43. package/dist/types/interfaces/graph.d.ts +1 -1
  44. package/dist/types/types/common.d.ts +2 -2
  45. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  46. package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
  47. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  48. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
  49. package/dist/types/types/utils/validate-type.d.ts +4 -4
  50. package/dist/umd/linked-list-typed.js +2589 -287
  51. package/dist/umd/linked-list-typed.js.map +1 -1
  52. package/dist/umd/linked-list-typed.min.js +1 -1
  53. package/dist/umd/linked-list-typed.min.js.map +1 -1
  54. package/package.json +2 -2
  55. package/src/data-structures/base/index.ts +1 -0
  56. package/src/data-structures/base/iterable-element-base.ts +4 -5
  57. package/src/data-structures/base/iterable-entry-base.ts +8 -8
  58. package/src/data-structures/base/linear-base.ts +3 -3
  59. package/src/data-structures/binary-tree/avl-tree.ts +386 -51
  60. package/src/data-structures/binary-tree/binary-indexed-tree.ts +596 -247
  61. package/src/data-structures/binary-tree/binary-tree.ts +956 -81
  62. package/src/data-structures/binary-tree/bst.ts +840 -35
  63. package/src/data-structures/binary-tree/red-black-tree.ts +689 -97
  64. package/src/data-structures/binary-tree/segment-tree.ts +498 -249
  65. package/src/data-structures/binary-tree/tree-map.ts +3784 -7
  66. package/src/data-structures/binary-tree/tree-multi-map.ts +3614 -211
  67. package/src/data-structures/binary-tree/tree-multi-set.ts +2874 -65
  68. package/src/data-structures/binary-tree/tree-set.ts +3531 -10
  69. package/src/data-structures/graph/abstract-graph.ts +4 -4
  70. package/src/data-structures/graph/directed-graph.ts +429 -47
  71. package/src/data-structures/graph/map-graph.ts +59 -1
  72. package/src/data-structures/graph/undirected-graph.ts +393 -59
  73. package/src/data-structures/hash/hash-map.ts +476 -92
  74. package/src/data-structures/heap/heap.ts +581 -99
  75. package/src/data-structures/heap/max-heap.ts +46 -0
  76. package/src/data-structures/heap/min-heap.ts +59 -0
  77. package/src/data-structures/linked-list/doubly-linked-list.ts +646 -47
  78. package/src/data-structures/linked-list/singly-linked-list.ts +596 -68
  79. package/src/data-structures/linked-list/skip-linked-list.ts +1067 -90
  80. package/src/data-structures/matrix/matrix.ts +584 -12
  81. package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
  82. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  83. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  84. package/src/data-structures/queue/deque.ts +592 -70
  85. package/src/data-structures/queue/queue.ts +463 -42
  86. package/src/data-structures/stack/stack.ts +384 -32
  87. package/src/data-structures/trie/trie.ts +470 -48
  88. package/src/interfaces/graph.ts +1 -1
  89. package/src/types/common.ts +2 -2
  90. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  91. package/src/types/data-structures/heap/heap.ts +1 -0
  92. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  93. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
  94. package/src/types/utils/validate-type.ts +4 -4
@@ -3,55 +3,6 @@
3
3
  var __defProp = Object.defineProperty;
4
4
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
5
5
 
6
- // src/common/error.ts
7
- var ERR = {
8
- // Range / index
9
- indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
10
- invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
11
- // Type / argument
12
- invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
13
- comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
14
- invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
15
- notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
16
- invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
17
- invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
18
- invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
19
- reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
20
- callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
21
- // State / operation
22
- invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
23
- // Matrix
24
- matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
25
- matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
26
- matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
27
- matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
28
- matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
29
- };
30
-
31
- // src/common/index.ts
32
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
33
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
34
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
35
- return DFSOperation2;
36
- })(DFSOperation || {});
37
- var Range = class {
38
- constructor(low, high, includeLow = true, includeHigh = true) {
39
- this.low = low;
40
- this.high = high;
41
- this.includeLow = includeLow;
42
- this.includeHigh = includeHigh;
43
- }
44
- static {
45
- __name(this, "Range");
46
- }
47
- // Determine whether a key is within the range
48
- isInRange(key, comparator) {
49
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
50
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
51
- return lowCheck && highCheck;
52
- }
53
- };
54
-
55
6
  // src/data-structures/base/iterable-element-base.ts
56
7
  var IterableElementBase = class {
57
8
  static {
@@ -70,7 +21,7 @@ var IterableElementBase = class {
70
21
  if (options) {
71
22
  const { toElementFn } = options;
72
23
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
73
- else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
24
+ else if (toElementFn) throw new TypeError("toElementFn must be a function type");
74
25
  }
75
26
  }
76
27
  /**
@@ -233,7 +184,7 @@ var IterableElementBase = class {
233
184
  acc = initialValue;
234
185
  } else {
235
186
  const first = iter.next();
236
- if (first.done) throw new TypeError(ERR.reduceEmpty());
187
+ if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
237
188
  acc = first.value;
238
189
  index = 1;
239
190
  }
@@ -774,11 +725,58 @@ var SinglyLinkedList = class extends LinearLinkedBase {
774
725
  return list;
775
726
  }
776
727
  /**
777
- * Append an element/node to the tail.
778
- * @remarks Time O(1), Space O(1)
779
- * @param elementOrNode - Element or node to append.
780
- * @returns True when appended.
781
- */
728
+ * Append an element/node to the tail.
729
+ * @remarks Time O(1), Space O(1)
730
+ * @param elementOrNode - Element or node to append.
731
+ * @returns True when appended.
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+ * @example
765
+ * // basic SinglyLinkedList creation and push operation
766
+ * // Create a simple SinglyLinkedList with initial values
767
+ * const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
768
+ *
769
+ * // Verify the list maintains insertion order
770
+ * console.log([...list]); // [1, 2, 3, 4, 5];
771
+ *
772
+ * // Check length
773
+ * console.log(list.length); // 5;
774
+ *
775
+ * // Push a new element to the end
776
+ * list.push(6);
777
+ * console.log(list.length); // 6;
778
+ * console.log([...list]); // [1, 2, 3, 4, 5, 6];
779
+ */
782
780
  push(elementOrNode) {
783
781
  const newNode = this._ensureNode(elementOrNode);
784
782
  if (!this.head) {
@@ -792,10 +790,57 @@ var SinglyLinkedList = class extends LinearLinkedBase {
792
790
  return true;
793
791
  }
794
792
  /**
795
- * Remove and return the tail element.
796
- * @remarks Time O(N), Space O(1)
797
- * @returns Removed element or undefined.
798
- */
793
+ * Remove and return the tail element.
794
+ * @remarks Time O(N), Space O(1)
795
+ * @returns Removed element or undefined.
796
+
797
+
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+
812
+
813
+
814
+
815
+
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+
824
+
825
+
826
+
827
+
828
+ * @example
829
+ * // SinglyLinkedList pop and shift operations
830
+ * const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
831
+ *
832
+ * // Pop removes from the end
833
+ * const last = list.pop();
834
+ * console.log(last); // 50;
835
+ *
836
+ * // Shift removes from the beginning
837
+ * const first = list.shift();
838
+ * console.log(first); // 10;
839
+ *
840
+ * // Verify remaining elements
841
+ * console.log([...list]); // [20, 30, 40];
842
+ * console.log(list.length); // 3;
843
+ */
799
844
  pop() {
800
845
  if (!this.head) return void 0;
801
846
  if (this.head === this.tail) {
@@ -814,10 +859,47 @@ var SinglyLinkedList = class extends LinearLinkedBase {
814
859
  return value;
815
860
  }
816
861
  /**
817
- * Remove and return the head element.
818
- * @remarks Time O(1), Space O(1)
819
- * @returns Removed element or undefined.
820
- */
862
+ * Remove and return the head element.
863
+ * @remarks Time O(1), Space O(1)
864
+ * @returns Removed element or undefined.
865
+
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+
881
+
882
+
883
+
884
+
885
+
886
+
887
+
888
+
889
+
890
+
891
+
892
+
893
+
894
+
895
+
896
+
897
+ * @example
898
+ * // Remove from the front
899
+ * const list = new SinglyLinkedList<number>([10, 20, 30]);
900
+ * console.log(list.shift()); // 10;
901
+ * console.log(list.length); // 2;
902
+ */
821
903
  shift() {
822
904
  if (!this.head) return void 0;
823
905
  const removed = this.head;
@@ -827,11 +909,63 @@ var SinglyLinkedList = class extends LinearLinkedBase {
827
909
  return removed.value;
828
910
  }
829
911
  /**
830
- * Prepend an element/node to the head.
831
- * @remarks Time O(1), Space O(1)
832
- * @param elementOrNode - Element or node to prepend.
833
- * @returns True when prepended.
834
- */
912
+ * Prepend an element/node to the head.
913
+ * @remarks Time O(1), Space O(1)
914
+ * @param elementOrNode - Element or node to prepend.
915
+ * @returns True when prepended.
916
+
917
+
918
+
919
+
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+ * @example
949
+ * // SinglyLinkedList unshift and forward traversal
950
+ * const list = new SinglyLinkedList<number>([20, 30, 40]);
951
+ *
952
+ * // Unshift adds to the beginning
953
+ * list.unshift(10);
954
+ * console.log([...list]); // [10, 20, 30, 40];
955
+ *
956
+ * // Access elements (forward traversal only for singly linked)
957
+ * const second = list.at(1);
958
+ * console.log(second); // 20;
959
+ *
960
+ * // SinglyLinkedList allows forward iteration only
961
+ * const elements: number[] = [];
962
+ * for (const item of list) {
963
+ * elements.push(item);
964
+ * }
965
+ * console.log(elements); // [10, 20, 30, 40];
966
+ *
967
+ * console.log(list.length); // 4;
968
+ */
835
969
  unshift(elementOrNode) {
836
970
  const newNode = this._ensureNode(elementOrNode);
837
971
  if (!this.head) {
@@ -887,11 +1021,49 @@ var SinglyLinkedList = class extends LinearLinkedBase {
887
1021
  return void 0;
888
1022
  }
889
1023
  /**
890
- * Get the element at a given index.
891
- * @remarks Time O(N), Space O(1)
892
- * @param index - Zero-based index.
893
- * @returns Element or undefined.
894
- */
1024
+ * Get the element at a given index.
1025
+ * @remarks Time O(N), Space O(1)
1026
+ * @param index - Zero-based index.
1027
+ * @returns Element or undefined.
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
1060
+ * @example
1061
+ * // Access element by index
1062
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
1063
+ * console.log(list.at(0)); // 'a';
1064
+ * console.log(list.at(2)); // 'c';
1065
+ * console.log(list.at(3)); // 'd';
1066
+ */
895
1067
  at(index) {
896
1068
  if (index < 0 || index >= this._length) return void 0;
897
1069
  let current = this.head;
@@ -908,11 +1080,44 @@ var SinglyLinkedList = class extends LinearLinkedBase {
908
1080
  return elementNodeOrPredicate instanceof SinglyLinkedListNode;
909
1081
  }
910
1082
  /**
911
- * Get the node reference at a given index.
912
- * @remarks Time O(N), Space O(1)
913
- * @param index - Zero-based index.
914
- * @returns Node or undefined.
915
- */
1083
+ * Get the node reference at a given index.
1084
+ * @remarks Time O(N), Space O(1)
1085
+ * @param index - Zero-based index.
1086
+ * @returns Node or undefined.
1087
+
1088
+
1089
+
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1097
+
1098
+
1099
+
1100
+
1101
+
1102
+
1103
+
1104
+
1105
+
1106
+
1107
+
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+ * @example
1117
+ * // Get node at index
1118
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
1119
+ * console.log(list.getNodeAt(1)?.value); // 'b';
1120
+ */
916
1121
  getNodeAt(index) {
917
1122
  if (index < 0 || index >= this._length) return void 0;
918
1123
  let current = this.head;
@@ -920,11 +1125,45 @@ var SinglyLinkedList = class extends LinearLinkedBase {
920
1125
  return current;
921
1126
  }
922
1127
  /**
923
- * Delete the element at an index.
924
- * @remarks Time O(N), Space O(1)
925
- * @param index - Zero-based index.
926
- * @returns Removed element or undefined.
927
- */
1128
+ * Delete the element at an index.
1129
+ * @remarks Time O(N), Space O(1)
1130
+ * @param index - Zero-based index.
1131
+ * @returns Removed element or undefined.
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+
1154
+
1155
+
1156
+
1157
+
1158
+
1159
+
1160
+
1161
+ * @example
1162
+ * // Remove by index
1163
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
1164
+ * list.deleteAt(1);
1165
+ * console.log(list.toArray()); // ['a', 'c'];
1166
+ */
928
1167
  deleteAt(index) {
929
1168
  if (index < 0 || index >= this._length) return void 0;
930
1169
  if (index === 0) return this.shift();
@@ -937,11 +1176,45 @@ var SinglyLinkedList = class extends LinearLinkedBase {
937
1176
  return value;
938
1177
  }
939
1178
  /**
940
- * Delete the first match by value/node.
941
- * @remarks Time O(N), Space O(1)
942
- * @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
943
- * @returns True if removed.
944
- */
1179
+ * Delete the first match by value/node.
1180
+ * @remarks Time O(N), Space O(1)
1181
+ * @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
1182
+ * @returns True if removed.
1183
+
1184
+
1185
+
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+
1196
+
1197
+
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+ * @example
1213
+ * // Remove first occurrence
1214
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
1215
+ * list.delete(2);
1216
+ * console.log(list.toArray()); // [1, 3, 2];
1217
+ */
945
1218
  delete(elementOrNode) {
946
1219
  if (elementOrNode === void 0 || !this.head) return false;
947
1220
  const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
@@ -958,12 +1231,46 @@ var SinglyLinkedList = class extends LinearLinkedBase {
958
1231
  return true;
959
1232
  }
960
1233
  /**
961
- * Insert a new element/node at an index, shifting following nodes.
962
- * @remarks Time O(N), Space O(1)
963
- * @param index - Zero-based index.
964
- * @param newElementOrNode - Element or node to insert.
965
- * @returns True if inserted.
966
- */
1234
+ * Insert a new element/node at an index, shifting following nodes.
1235
+ * @remarks Time O(N), Space O(1)
1236
+ * @param index - Zero-based index.
1237
+ * @param newElementOrNode - Element or node to insert.
1238
+ * @returns True if inserted.
1239
+
1240
+
1241
+
1242
+
1243
+
1244
+
1245
+
1246
+
1247
+
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1262
+
1263
+
1264
+
1265
+
1266
+
1267
+
1268
+ * @example
1269
+ * // Insert at index
1270
+ * const list = new SinglyLinkedList<number>([1, 3]);
1271
+ * list.addAt(1, 2);
1272
+ * console.log(list.toArray()); // [1, 2, 3];
1273
+ */
967
1274
  addAt(index, newElementOrNode) {
968
1275
  if (index < 0 || index > this._length) return false;
969
1276
  if (index === 0) return this.unshift(newElementOrNode);
@@ -989,28 +1296,133 @@ var SinglyLinkedList = class extends LinearLinkedBase {
989
1296
  return true;
990
1297
  }
991
1298
  /**
992
- * Check whether the list is empty.
993
- * @remarks Time O(1), Space O(1)
994
- * @returns True if length is 0.
995
- */
1299
+ * Check whether the list is empty.
1300
+ * @remarks Time O(1), Space O(1)
1301
+ * @returns True if length is 0.
1302
+
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+
1310
+
1311
+
1312
+
1313
+
1314
+
1315
+
1316
+
1317
+
1318
+
1319
+
1320
+
1321
+
1322
+
1323
+
1324
+
1325
+
1326
+
1327
+
1328
+
1329
+
1330
+
1331
+
1332
+ * @example
1333
+ * // Check empty
1334
+ * console.log(new SinglyLinkedList().isEmpty()); // true;
1335
+ */
996
1336
  isEmpty() {
997
1337
  return this._length === 0;
998
1338
  }
999
1339
  /**
1000
- * Remove all nodes and reset length.
1001
- * @remarks Time O(N), Space O(1)
1002
- * @returns void
1003
- */
1340
+ * Remove all nodes and reset length.
1341
+ * @remarks Time O(N), Space O(1)
1342
+ * @returns void
1343
+
1344
+
1345
+
1346
+
1347
+
1348
+
1349
+
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+
1359
+
1360
+
1361
+
1362
+
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+
1371
+
1372
+
1373
+ * @example
1374
+ * // Remove all
1375
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1376
+ * list.clear();
1377
+ * console.log(list.isEmpty()); // true;
1378
+ */
1004
1379
  clear() {
1005
1380
  this._head = void 0;
1006
1381
  this._tail = void 0;
1007
1382
  this._length = 0;
1008
1383
  }
1009
1384
  /**
1010
- * Reverse the list in place.
1011
- * @remarks Time O(N), Space O(1)
1012
- * @returns This list.
1013
- */
1385
+ * Reverse the list in place.
1386
+ * @remarks Time O(N), Space O(1)
1387
+ * @returns This list.
1388
+
1389
+
1390
+
1391
+
1392
+
1393
+
1394
+
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+
1404
+
1405
+
1406
+
1407
+
1408
+
1409
+
1410
+
1411
+
1412
+
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+ * @example
1421
+ * // Reverse the list in-place
1422
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
1423
+ * list.reverse();
1424
+ * console.log([...list]); // [4, 3, 2, 1];
1425
+ */
1014
1426
  reverse() {
1015
1427
  if (!this.head || this.head === this.tail) return this;
1016
1428
  let prev;
@@ -1185,22 +1597,106 @@ var SinglyLinkedList = class extends LinearLinkedBase {
1185
1597
  return false;
1186
1598
  }
1187
1599
  /**
1188
- * Deep clone this list (values are copied by reference).
1189
- * @remarks Time O(N), Space O(N)
1190
- * @returns A new list with the same element sequence.
1191
- */
1600
+ * Deep clone this list (values are copied by reference).
1601
+ * @remarks Time O(N), Space O(N)
1602
+ * @returns A new list with the same element sequence.
1603
+
1604
+
1605
+
1606
+
1607
+
1608
+
1609
+
1610
+
1611
+
1612
+
1613
+
1614
+
1615
+
1616
+
1617
+
1618
+
1619
+
1620
+
1621
+
1622
+
1623
+
1624
+
1625
+
1626
+
1627
+
1628
+
1629
+
1630
+
1631
+
1632
+
1633
+ * @example
1634
+ * // Deep copy
1635
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1636
+ * const copy = list.clone();
1637
+ * copy.pop();
1638
+ * console.log(list.length); // 3;
1639
+ * console.log(copy.length); // 2;
1640
+ */
1192
1641
  clone() {
1193
1642
  const out = this._createInstance();
1194
1643
  for (const v of this) out.push(v);
1195
1644
  return out;
1196
1645
  }
1197
1646
  /**
1198
- * Filter values into a new list of the same class.
1199
- * @remarks Time O(N), Space O(N)
1200
- * @param callback - Predicate (value, index, list) → boolean to keep value.
1201
- * @param [thisArg] - Value for `this` inside the callback.
1202
- * @returns A new list with kept values.
1203
- */
1647
+ * Filter values into a new list of the same class.
1648
+ * @remarks Time O(N), Space O(N)
1649
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
1650
+ * @param [thisArg] - Value for `this` inside the callback.
1651
+ * @returns A new list with kept values.
1652
+
1653
+
1654
+
1655
+
1656
+
1657
+
1658
+
1659
+
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+
1666
+
1667
+
1668
+
1669
+
1670
+
1671
+
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+
1681
+
1682
+
1683
+
1684
+ * @example
1685
+ * // SinglyLinkedList filter and map operations
1686
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
1687
+ *
1688
+ * // Filter even numbers
1689
+ * const filtered = list.filter(value => value % 2 === 0);
1690
+ * console.log(filtered.length); // 2;
1691
+ *
1692
+ * // Map to double values
1693
+ * const doubled = list.map(value => value * 2);
1694
+ * console.log(doubled.length); // 5;
1695
+ *
1696
+ * // Use reduce to sum
1697
+ * const sum = list.reduce((acc, value) => acc + value, 0);
1698
+ * console.log(sum); // 15;
1699
+ */
1204
1700
  filter(callback, thisArg) {
1205
1701
  const out = this._createInstance();
1206
1702
  let index = 0;
@@ -1224,15 +1720,52 @@ var SinglyLinkedList = class extends LinearLinkedBase {
1224
1720
  return out;
1225
1721
  }
1226
1722
  /**
1227
- * Map values into a new list (possibly different element type).
1228
- * @remarks Time O(N), Space O(N)
1229
- * @template EM
1230
- * @template RM
1231
- * @param callback - Mapping function (value, index, list) → newElement.
1232
- * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1233
- * @param [thisArg] - Value for `this` inside the callback.
1234
- * @returns A new SinglyLinkedList with mapped values.
1235
- */
1723
+ * Map values into a new list (possibly different element type).
1724
+ * @remarks Time O(N), Space O(N)
1725
+ * @template EM
1726
+ * @template RM
1727
+ * @param callback - Mapping function (value, index, list) → newElement.
1728
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1729
+ * @param [thisArg] - Value for `this` inside the callback.
1730
+ * @returns A new SinglyLinkedList with mapped values.
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+
1750
+
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+
1761
+
1762
+
1763
+ * @example
1764
+ * // Transform elements
1765
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1766
+ * const doubled = list.map(n => n * 2);
1767
+ * console.log([...doubled]); // [2, 4, 6];
1768
+ */
1236
1769
  map(callback, options, thisArg) {
1237
1770
  const out = this._createLike([], { ...options ?? {}, maxLen: this._maxLen });
1238
1771
  let index = 0;
@@ -1508,11 +2041,58 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1508
2041
  return elementNodeOrPredicate instanceof DoublyLinkedListNode;
1509
2042
  }
1510
2043
  /**
1511
- * Append an element/node to the tail.
1512
- * @remarks Time O(1), Space O(1)
1513
- * @param elementOrNode - Element or node to append.
1514
- * @returns True when appended.
1515
- */
2044
+ * Append an element/node to the tail.
2045
+ * @remarks Time O(1), Space O(1)
2046
+ * @param elementOrNode - Element or node to append.
2047
+ * @returns True when appended.
2048
+
2049
+
2050
+
2051
+
2052
+
2053
+
2054
+
2055
+
2056
+
2057
+
2058
+
2059
+
2060
+
2061
+
2062
+
2063
+
2064
+
2065
+
2066
+
2067
+
2068
+
2069
+
2070
+
2071
+
2072
+
2073
+
2074
+
2075
+
2076
+
2077
+
2078
+
2079
+
2080
+ * @example
2081
+ * // basic DoublyLinkedList creation and push operation
2082
+ * // Create a simple DoublyLinkedList with initial values
2083
+ * const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
2084
+ *
2085
+ * // Verify the list maintains insertion order
2086
+ * console.log([...list]); // [1, 2, 3, 4, 5];
2087
+ *
2088
+ * // Check length
2089
+ * console.log(list.length); // 5;
2090
+ *
2091
+ * // Push a new element to the end
2092
+ * list.push(6);
2093
+ * console.log(list.length); // 6;
2094
+ * console.log([...list]); // [1, 2, 3, 4, 5, 6];
2095
+ */
1516
2096
  push(elementOrNode) {
1517
2097
  const newNode = this._ensureNode(elementOrNode);
1518
2098
  if (!this.head) {
@@ -1528,10 +2108,57 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1528
2108
  return true;
1529
2109
  }
1530
2110
  /**
1531
- * Remove and return the tail element.
1532
- * @remarks Time O(1), Space O(1)
1533
- * @returns Removed element or undefined.
1534
- */
2111
+ * Remove and return the tail element.
2112
+ * @remarks Time O(1), Space O(1)
2113
+ * @returns Removed element or undefined.
2114
+
2115
+
2116
+
2117
+
2118
+
2119
+
2120
+
2121
+
2122
+
2123
+
2124
+
2125
+
2126
+
2127
+
2128
+
2129
+
2130
+
2131
+
2132
+
2133
+
2134
+
2135
+
2136
+
2137
+
2138
+
2139
+
2140
+
2141
+
2142
+
2143
+
2144
+
2145
+
2146
+ * @example
2147
+ * // DoublyLinkedList pop and shift operations
2148
+ * const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
2149
+ *
2150
+ * // Pop removes from the end
2151
+ * const last = list.pop();
2152
+ * console.log(last); // 50;
2153
+ *
2154
+ * // Shift removes from the beginning
2155
+ * const first = list.shift();
2156
+ * console.log(first); // 10;
2157
+ *
2158
+ * // Verify remaining elements
2159
+ * console.log([...list]); // [20, 30, 40];
2160
+ * console.log(list.length); // 3;
2161
+ */
1535
2162
  pop() {
1536
2163
  if (!this.tail) return void 0;
1537
2164
  const removed = this.tail;
@@ -1546,10 +2173,47 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1546
2173
  return removed.value;
1547
2174
  }
1548
2175
  /**
1549
- * Remove and return the head element.
1550
- * @remarks Time O(1), Space O(1)
1551
- * @returns Removed element or undefined.
1552
- */
2176
+ * Remove and return the head element.
2177
+ * @remarks Time O(1), Space O(1)
2178
+ * @returns Removed element or undefined.
2179
+
2180
+
2181
+
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+
2188
+
2189
+
2190
+
2191
+
2192
+
2193
+
2194
+
2195
+
2196
+
2197
+
2198
+
2199
+
2200
+
2201
+
2202
+
2203
+
2204
+
2205
+
2206
+
2207
+
2208
+
2209
+
2210
+
2211
+ * @example
2212
+ * // Remove from the front
2213
+ * const list = new DoublyLinkedList<number>([10, 20, 30]);
2214
+ * console.log(list.shift()); // 10;
2215
+ * console.log(list.first); // 20;
2216
+ */
1553
2217
  shift() {
1554
2218
  if (!this.head) return void 0;
1555
2219
  const removed = this.head;
@@ -1564,11 +2228,48 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1564
2228
  return removed.value;
1565
2229
  }
1566
2230
  /**
1567
- * Prepend an element/node to the head.
1568
- * @remarks Time O(1), Space O(1)
1569
- * @param elementOrNode - Element or node to prepend.
1570
- * @returns True when prepended.
1571
- */
2231
+ * Prepend an element/node to the head.
2232
+ * @remarks Time O(1), Space O(1)
2233
+ * @param elementOrNode - Element or node to prepend.
2234
+ * @returns True when prepended.
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+
2244
+
2245
+
2246
+
2247
+
2248
+
2249
+
2250
+
2251
+
2252
+
2253
+
2254
+
2255
+
2256
+
2257
+
2258
+
2259
+
2260
+
2261
+
2262
+
2263
+
2264
+
2265
+
2266
+
2267
+ * @example
2268
+ * // Add to the front
2269
+ * const list = new DoublyLinkedList<number>([2, 3]);
2270
+ * list.unshift(1);
2271
+ * console.log([...list]); // [1, 2, 3];
2272
+ */
1572
2273
  unshift(elementOrNode) {
1573
2274
  const newNode = this._ensureNode(elementOrNode);
1574
2275
  if (!this.head) {
@@ -1612,11 +2313,48 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1612
2313
  return ans;
1613
2314
  }
1614
2315
  /**
1615
- * Get the element at a given index.
1616
- * @remarks Time O(N), Space O(1)
1617
- * @param index - Zero-based index.
1618
- * @returns Element or undefined.
1619
- */
2316
+ * Get the element at a given index.
2317
+ * @remarks Time O(N), Space O(1)
2318
+ * @param index - Zero-based index.
2319
+ * @returns Element or undefined.
2320
+
2321
+
2322
+
2323
+
2324
+
2325
+
2326
+
2327
+
2328
+
2329
+
2330
+
2331
+
2332
+
2333
+
2334
+
2335
+
2336
+
2337
+
2338
+
2339
+
2340
+
2341
+
2342
+
2343
+
2344
+
2345
+
2346
+
2347
+
2348
+
2349
+
2350
+
2351
+
2352
+ * @example
2353
+ * // Access by index
2354
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
2355
+ * console.log(list.at(1)); // 'b';
2356
+ * console.log(list.at(2)); // 'c';
2357
+ */
1620
2358
  at(index) {
1621
2359
  if (index < 0 || index >= this._length) return void 0;
1622
2360
  let current = this.head;
@@ -1624,11 +2362,44 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1624
2362
  return current?.value;
1625
2363
  }
1626
2364
  /**
1627
- * Get the node reference at a given index.
1628
- * @remarks Time O(N), Space O(1)
1629
- * @param index - Zero-based index.
1630
- * @returns Node or undefined.
1631
- */
2365
+ * Get the node reference at a given index.
2366
+ * @remarks Time O(N), Space O(1)
2367
+ * @param index - Zero-based index.
2368
+ * @returns Node or undefined.
2369
+
2370
+
2371
+
2372
+
2373
+
2374
+
2375
+
2376
+
2377
+
2378
+
2379
+
2380
+
2381
+
2382
+
2383
+
2384
+
2385
+
2386
+
2387
+
2388
+
2389
+
2390
+
2391
+
2392
+
2393
+
2394
+
2395
+
2396
+
2397
+
2398
+ * @example
2399
+ * // Get node at index
2400
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
2401
+ * console.log(list.getNodeAt(1)?.value); // 'b';
2402
+ */
1632
2403
  getNodeAt(index) {
1633
2404
  if (index < 0 || index >= this._length) return void 0;
1634
2405
  let current = this.head;
@@ -1667,12 +2438,46 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1667
2438
  return void 0;
1668
2439
  }
1669
2440
  /**
1670
- * Insert a new element/node at an index, shifting following nodes.
1671
- * @remarks Time O(N), Space O(1)
1672
- * @param index - Zero-based index.
1673
- * @param newElementOrNode - Element or node to insert.
1674
- * @returns True if inserted.
1675
- */
2441
+ * Insert a new element/node at an index, shifting following nodes.
2442
+ * @remarks Time O(N), Space O(1)
2443
+ * @param index - Zero-based index.
2444
+ * @param newElementOrNode - Element or node to insert.
2445
+ * @returns True if inserted.
2446
+
2447
+
2448
+
2449
+
2450
+
2451
+
2452
+
2453
+
2454
+
2455
+
2456
+
2457
+
2458
+
2459
+
2460
+
2461
+
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+
2469
+
2470
+
2471
+
2472
+
2473
+
2474
+
2475
+ * @example
2476
+ * // Insert at position
2477
+ * const list = new DoublyLinkedList<number>([1, 3]);
2478
+ * list.addAt(1, 2);
2479
+ * console.log(list.toArray()); // [1, 2, 3];
2480
+ */
1676
2481
  addAt(index, newElementOrNode) {
1677
2482
  if (index < 0 || index > this._length) return false;
1678
2483
  if (index === 0) return this.unshift(newElementOrNode);
@@ -1739,11 +2544,45 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1739
2544
  return true;
1740
2545
  }
1741
2546
  /**
1742
- * Delete the element at an index.
1743
- * @remarks Time O(N), Space O(1)
1744
- * @param index - Zero-based index.
1745
- * @returns Removed element or undefined.
1746
- */
2547
+ * Delete the element at an index.
2548
+ * @remarks Time O(N), Space O(1)
2549
+ * @param index - Zero-based index.
2550
+ * @returns Removed element or undefined.
2551
+
2552
+
2553
+
2554
+
2555
+
2556
+
2557
+
2558
+
2559
+
2560
+
2561
+
2562
+
2563
+
2564
+
2565
+
2566
+
2567
+
2568
+
2569
+
2570
+
2571
+
2572
+
2573
+
2574
+
2575
+
2576
+
2577
+
2578
+
2579
+
2580
+ * @example
2581
+ * // Remove by index
2582
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
2583
+ * list.deleteAt(1);
2584
+ * console.log(list.toArray()); // ['a', 'c'];
2585
+ */
1747
2586
  deleteAt(index) {
1748
2587
  if (index < 0 || index >= this._length) return;
1749
2588
  if (index === 0) return this.shift();
@@ -1757,11 +2596,45 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1757
2596
  return removedNode.value;
1758
2597
  }
1759
2598
  /**
1760
- * Delete the first match by value/node.
1761
- * @remarks Time O(N), Space O(1)
1762
- * @param [elementOrNode] - Element or node to remove.
1763
- * @returns True if removed.
1764
- */
2599
+ * Delete the first match by value/node.
2600
+ * @remarks Time O(N), Space O(1)
2601
+ * @param [elementOrNode] - Element or node to remove.
2602
+ * @returns True if removed.
2603
+
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+
2614
+
2615
+
2616
+
2617
+
2618
+
2619
+
2620
+
2621
+
2622
+
2623
+
2624
+
2625
+
2626
+
2627
+
2628
+
2629
+
2630
+
2631
+
2632
+ * @example
2633
+ * // Remove first occurrence
2634
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
2635
+ * list.delete(2);
2636
+ * console.log(list.toArray()); // [1, 3, 2];
2637
+ */
1765
2638
  delete(elementOrNode) {
1766
2639
  const node = this.getNode(elementOrNode);
1767
2640
  if (!node) return false;
@@ -1777,29 +2650,131 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1777
2650
  return true;
1778
2651
  }
1779
2652
  /**
1780
- * Check whether the list is empty.
1781
- * @remarks Time O(1), Space O(1)
1782
- * @returns True if length is 0.
1783
- */
2653
+ * Check whether the list is empty.
2654
+ * @remarks Time O(1), Space O(1)
2655
+ * @returns True if length is 0.
2656
+
2657
+
2658
+
2659
+
2660
+
2661
+
2662
+
2663
+
2664
+
2665
+
2666
+
2667
+
2668
+
2669
+
2670
+
2671
+
2672
+
2673
+
2674
+
2675
+
2676
+
2677
+
2678
+
2679
+
2680
+
2681
+
2682
+
2683
+
2684
+
2685
+
2686
+ * @example
2687
+ * // Check empty
2688
+ * console.log(new DoublyLinkedList().isEmpty()); // true;
2689
+ */
1784
2690
  isEmpty() {
1785
2691
  return this._length === 0;
1786
2692
  }
1787
2693
  /**
1788
- * Remove all nodes and reset length.
1789
- * @remarks Time O(N), Space O(1)
1790
- * @returns void
1791
- */
2694
+ * Remove all nodes and reset length.
2695
+ * @remarks Time O(N), Space O(1)
2696
+ * @returns void
2697
+
2698
+
2699
+
2700
+
2701
+
2702
+
2703
+
2704
+
2705
+
2706
+
2707
+
2708
+
2709
+
2710
+
2711
+
2712
+
2713
+
2714
+
2715
+
2716
+
2717
+
2718
+
2719
+
2720
+
2721
+
2722
+
2723
+
2724
+
2725
+
2726
+
2727
+ * @example
2728
+ * // Remove all
2729
+ * const list = new DoublyLinkedList<number>([1, 2]);
2730
+ * list.clear();
2731
+ * console.log(list.isEmpty()); // true;
2732
+ */
1792
2733
  clear() {
1793
2734
  this._head = void 0;
1794
2735
  this._tail = void 0;
1795
2736
  this._length = 0;
1796
2737
  }
1797
2738
  /**
1798
- * Find the first value matching a predicate scanning forward.
1799
- * @remarks Time O(N), Space O(1)
1800
- * @param elementNodeOrPredicate - Element, node, or predicate to match.
1801
- * @returns Matched value or undefined.
1802
- */
2739
+ * Find the first value matching a predicate scanning forward.
2740
+ * @remarks Time O(N), Space O(1)
2741
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
2742
+ * @returns Matched value or undefined.
2743
+
2744
+
2745
+
2746
+
2747
+
2748
+
2749
+
2750
+
2751
+
2752
+
2753
+
2754
+
2755
+
2756
+
2757
+
2758
+
2759
+
2760
+
2761
+
2762
+
2763
+
2764
+
2765
+
2766
+
2767
+
2768
+
2769
+
2770
+
2771
+
2772
+ * @example
2773
+ * // Search with predicate
2774
+ * const list = new DoublyLinkedList<number>([10, 20, 30]);
2775
+ * const found = list.search(node => node.value > 15);
2776
+ * console.log(found); // 20;
2777
+ */
1803
2778
  search(elementNodeOrPredicate) {
1804
2779
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
1805
2780
  let current = this.head;
@@ -1810,11 +2785,46 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1810
2785
  return void 0;
1811
2786
  }
1812
2787
  /**
1813
- * Find the first value matching a predicate scanning backward.
1814
- * @remarks Time O(N), Space O(1)
1815
- * @param elementNodeOrPredicate - Element, node, or predicate to match.
1816
- * @returns Matched value or undefined.
1817
- */
2788
+ * Find the first value matching a predicate scanning backward.
2789
+ * @remarks Time O(N), Space O(1)
2790
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
2791
+ * @returns Matched value or undefined.
2792
+
2793
+
2794
+
2795
+
2796
+
2797
+
2798
+
2799
+
2800
+
2801
+
2802
+
2803
+
2804
+
2805
+
2806
+
2807
+
2808
+
2809
+
2810
+
2811
+
2812
+
2813
+
2814
+
2815
+
2816
+
2817
+
2818
+
2819
+
2820
+
2821
+ * @example
2822
+ * // Find value scanning from tail
2823
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
2824
+ * // getBackward scans from tail to head, returns first match
2825
+ * const found = list.getBackward(node => node.value < 4);
2826
+ * console.log(found); // 3;
2827
+ */
1818
2828
  getBackward(elementNodeOrPredicate) {
1819
2829
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
1820
2830
  let current = this.tail;
@@ -1825,10 +2835,47 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1825
2835
  return void 0;
1826
2836
  }
1827
2837
  /**
1828
- * Reverse the list in place.
1829
- * @remarks Time O(N), Space O(1)
1830
- * @returns This list.
1831
- */
2838
+ * Reverse the list in place.
2839
+ * @remarks Time O(N), Space O(1)
2840
+ * @returns This list.
2841
+
2842
+
2843
+
2844
+
2845
+
2846
+
2847
+
2848
+
2849
+
2850
+
2851
+
2852
+
2853
+
2854
+
2855
+
2856
+
2857
+
2858
+
2859
+
2860
+
2861
+
2862
+
2863
+
2864
+
2865
+
2866
+
2867
+
2868
+
2869
+
2870
+
2871
+
2872
+
2873
+ * @example
2874
+ * // Reverse in-place
2875
+ * const list = new DoublyLinkedList<number>([1, 2, 3]);
2876
+ * list.reverse();
2877
+ * console.log([...list]); // [3, 2, 1];
2878
+ */
1832
2879
  reverse() {
1833
2880
  let current = this.head;
1834
2881
  [this._head, this._tail] = [this.tail, this.head];
@@ -1850,22 +2897,95 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1850
2897
  return this;
1851
2898
  }
1852
2899
  /**
1853
- * Deep clone this list (values are copied by reference).
1854
- * @remarks Time O(N), Space O(N)
1855
- * @returns A new list with the same element sequence.
1856
- */
2900
+ * Deep clone this list (values are copied by reference).
2901
+ * @remarks Time O(N), Space O(N)
2902
+ * @returns A new list with the same element sequence.
2903
+
2904
+
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+
2911
+
2912
+
2913
+
2914
+
2915
+
2916
+
2917
+
2918
+
2919
+
2920
+
2921
+
2922
+
2923
+
2924
+
2925
+
2926
+
2927
+
2928
+
2929
+
2930
+
2931
+
2932
+
2933
+ * @example
2934
+ * // Deep copy
2935
+ * const list = new DoublyLinkedList<number>([1, 2, 3]);
2936
+ * const copy = list.clone();
2937
+ * copy.pop();
2938
+ * console.log(list.length); // 3;
2939
+ */
1857
2940
  clone() {
1858
2941
  const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1859
2942
  for (const v of this) out.push(v);
1860
2943
  return out;
1861
2944
  }
1862
2945
  /**
1863
- * Filter values into a new list of the same class.
1864
- * @remarks Time O(N), Space O(N)
1865
- * @param callback - Predicate (value, index, list) → boolean to keep value.
1866
- * @param [thisArg] - Value for `this` inside the callback.
1867
- * @returns A new list with kept values.
1868
- */
2946
+ * Filter values into a new list of the same class.
2947
+ * @remarks Time O(N), Space O(N)
2948
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
2949
+ * @param [thisArg] - Value for `this` inside the callback.
2950
+ * @returns A new list with kept values.
2951
+
2952
+
2953
+
2954
+
2955
+
2956
+
2957
+
2958
+
2959
+
2960
+
2961
+
2962
+
2963
+
2964
+
2965
+
2966
+
2967
+
2968
+
2969
+
2970
+
2971
+
2972
+
2973
+
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+
2983
+ * @example
2984
+ * // Filter elements
2985
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
2986
+ * const evens = list.filter(n => n % 2 === 0);
2987
+ * console.log([...evens]); // [2, 4];
2988
+ */
1869
2989
  filter(callback, thisArg) {
1870
2990
  const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1871
2991
  let index = 0;
@@ -1889,15 +3009,61 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1889
3009
  return out;
1890
3010
  }
1891
3011
  /**
1892
- * Map values into a new list (possibly different element type).
1893
- * @remarks Time O(N), Space O(N)
1894
- * @template EM
1895
- * @template RM
1896
- * @param callback - Mapping function (value, index, list) → newElement.
1897
- * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1898
- * @param [thisArg] - Value for `this` inside the callback.
1899
- * @returns A new DoublyLinkedList with mapped values.
1900
- */
3012
+ * Map values into a new list (possibly different element type).
3013
+ * @remarks Time O(N), Space O(N)
3014
+ * @template EM
3015
+ * @template RM
3016
+ * @param callback - Mapping function (value, index, list) → newElement.
3017
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
3018
+ * @param [thisArg] - Value for `this` inside the callback.
3019
+ * @returns A new DoublyLinkedList with mapped values.
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+
3029
+
3030
+
3031
+
3032
+
3033
+
3034
+
3035
+
3036
+
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+
3043
+
3044
+
3045
+
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+ * @example
3053
+ * // DoublyLinkedList for...of iteration and map operation
3054
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
3055
+ *
3056
+ * // Iterate through list
3057
+ * const doubled = list.map(value => value * 2);
3058
+ * console.log(doubled.length); // 5;
3059
+ *
3060
+ * // Use for...of loop
3061
+ * const result: number[] = [];
3062
+ * for (const item of list) {
3063
+ * result.push(item);
3064
+ * }
3065
+ * console.log(result); // [1, 2, 3, 4, 5];
3066
+ */
1901
3067
  map(callback, options, thisArg) {
1902
3068
  const out = this._createLike([], { ...options ?? {}, maxLen: this._maxLen });
1903
3069
  let index = 0;
@@ -1986,6 +3152,237 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1986
3152
  }
1987
3153
  };
1988
3154
 
3155
+ // src/common/error.ts
3156
+ var ERR = {
3157
+ // Range / index
3158
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
3159
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
3160
+ // Type / argument
3161
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
3162
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
3163
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
3164
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
3165
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
3166
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
3167
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
3168
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
3169
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
3170
+ // State / operation
3171
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
3172
+ // Matrix
3173
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
3174
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
3175
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
3176
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
3177
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
3178
+ };
3179
+
3180
+ // src/common/index.ts
3181
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
3182
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
3183
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
3184
+ return DFSOperation2;
3185
+ })(DFSOperation || {});
3186
+ var Range = class {
3187
+ constructor(low, high, includeLow = true, includeHigh = true) {
3188
+ this.low = low;
3189
+ this.high = high;
3190
+ this.includeLow = includeLow;
3191
+ this.includeHigh = includeHigh;
3192
+ }
3193
+ static {
3194
+ __name(this, "Range");
3195
+ }
3196
+ // Determine whether a key is within the range
3197
+ isInRange(key, comparator) {
3198
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
3199
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
3200
+ return lowCheck && highCheck;
3201
+ }
3202
+ };
3203
+
3204
+ // src/data-structures/base/iterable-entry-base.ts
3205
+ var IterableEntryBase = class {
3206
+ static {
3207
+ __name(this, "IterableEntryBase");
3208
+ }
3209
+ /**
3210
+ * Default iterator yielding `[key, value]` entries.
3211
+ * @returns Iterator of `[K, V]`.
3212
+ * @remarks Time O(n) to iterate, Space O(1)
3213
+ */
3214
+ *[Symbol.iterator](...args) {
3215
+ yield* this._getIterator(...args);
3216
+ }
3217
+ /**
3218
+ * Iterate over `[key, value]` pairs (may yield `undefined` values).
3219
+ * @returns Iterator of `[K, V | undefined]`.
3220
+ * @remarks Time O(n), Space O(1)
3221
+ */
3222
+ *entries() {
3223
+ for (const item of this) {
3224
+ yield item;
3225
+ }
3226
+ }
3227
+ /**
3228
+ * Iterate over keys only.
3229
+ * @returns Iterator of keys.
3230
+ * @remarks Time O(n), Space O(1)
3231
+ */
3232
+ *keys() {
3233
+ for (const item of this) {
3234
+ yield item[0];
3235
+ }
3236
+ }
3237
+ /**
3238
+ * Iterate over values only.
3239
+ * @returns Iterator of values.
3240
+ * @remarks Time O(n), Space O(1)
3241
+ */
3242
+ *values() {
3243
+ for (const item of this) {
3244
+ yield item[1];
3245
+ }
3246
+ }
3247
+ /**
3248
+ * Test whether all entries satisfy the predicate.
3249
+ * @param predicate - `(key, value, index, self) => boolean`.
3250
+ * @param thisArg - Optional `this` for callback.
3251
+ * @returns `true` if all pass; otherwise `false`.
3252
+ * @remarks Time O(n), Space O(1)
3253
+ */
3254
+ every(predicate, thisArg) {
3255
+ let index = 0;
3256
+ for (const item of this) {
3257
+ if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
3258
+ return false;
3259
+ }
3260
+ }
3261
+ return true;
3262
+ }
3263
+ /**
3264
+ * Test whether any entry satisfies the predicate.
3265
+ * @param predicate - `(key, value, index, self) => boolean`.
3266
+ * @param thisArg - Optional `this` for callback.
3267
+ * @returns `true` if any passes; otherwise `false`.
3268
+ * @remarks Time O(n), Space O(1)
3269
+ */
3270
+ some(predicate, thisArg) {
3271
+ let index = 0;
3272
+ for (const item of this) {
3273
+ if (predicate.call(thisArg, item[1], item[0], index++, this)) {
3274
+ return true;
3275
+ }
3276
+ }
3277
+ return false;
3278
+ }
3279
+ /**
3280
+ * Visit each entry, left-to-right.
3281
+ * @param callbackfn - `(key, value, index, self) => void`.
3282
+ * @param thisArg - Optional `this` for callback.
3283
+ * @remarks Time O(n), Space O(1)
3284
+ */
3285
+ forEach(callbackfn, thisArg) {
3286
+ let index = 0;
3287
+ for (const item of this) {
3288
+ const [key, value] = item;
3289
+ callbackfn.call(thisArg, value, key, index++, this);
3290
+ }
3291
+ }
3292
+ /**
3293
+ * Find the first entry that matches a predicate.
3294
+ * @param callbackfn - `(key, value, index, self) => boolean`.
3295
+ * @param thisArg - Optional `this` for callback.
3296
+ * @returns Matching `[key, value]` or `undefined`.
3297
+ * @remarks Time O(n), Space O(1)
3298
+ */
3299
+ find(callbackfn, thisArg) {
3300
+ let index = 0;
3301
+ for (const item of this) {
3302
+ const [key, value] = item;
3303
+ if (callbackfn.call(thisArg, value, key, index++, this)) return item;
3304
+ }
3305
+ return;
3306
+ }
3307
+ /**
3308
+ * Whether the given key exists.
3309
+ * @param key - Key to test.
3310
+ * @returns `true` if found; otherwise `false`.
3311
+ * @remarks Time O(n) generic, Space O(1)
3312
+ */
3313
+ has(key) {
3314
+ for (const item of this) {
3315
+ const [itemKey] = item;
3316
+ if (itemKey === key) return true;
3317
+ }
3318
+ return false;
3319
+ }
3320
+ /**
3321
+ * Whether there exists an entry with the given value.
3322
+ * @param value - Value to test.
3323
+ * @returns `true` if found; otherwise `false`.
3324
+ * @remarks Time O(n), Space O(1)
3325
+ */
3326
+ hasValue(value) {
3327
+ for (const [, elementValue] of this) {
3328
+ if (elementValue === value) return true;
3329
+ }
3330
+ return false;
3331
+ }
3332
+ /**
3333
+ * Get the value under a key.
3334
+ * @param key - Key to look up.
3335
+ * @returns Value or `undefined`.
3336
+ * @remarks Time O(n) generic, Space O(1)
3337
+ */
3338
+ get(key) {
3339
+ for (const item of this) {
3340
+ const [itemKey, value] = item;
3341
+ if (itemKey === key) return value;
3342
+ }
3343
+ return;
3344
+ }
3345
+ /**
3346
+ * Reduce entries into a single accumulator.
3347
+ * @param callbackfn - `(acc, value, key, index, self) => acc`.
3348
+ * @param initialValue - Initial accumulator.
3349
+ * @returns Final accumulator.
3350
+ * @remarks Time O(n), Space O(1)
3351
+ */
3352
+ reduce(callbackfn, initialValue) {
3353
+ let accumulator = initialValue;
3354
+ let index = 0;
3355
+ for (const item of this) {
3356
+ const [key, value] = item;
3357
+ accumulator = callbackfn(accumulator, value, key, index++, this);
3358
+ }
3359
+ return accumulator;
3360
+ }
3361
+ /**
3362
+ * Converts data structure to `[key, value]` pairs.
3363
+ * @returns Array of entries.
3364
+ * @remarks Time O(n), Space O(n)
3365
+ */
3366
+ toArray() {
3367
+ return [...this];
3368
+ }
3369
+ /**
3370
+ * Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
3371
+ * @returns Array of entries (default) or a string.
3372
+ * @remarks Time O(n), Space O(n)
3373
+ */
3374
+ toVisual() {
3375
+ return [...this];
3376
+ }
3377
+ /**
3378
+ * Print a human-friendly representation to the console.
3379
+ * @remarks Time O(n), Space O(n)
3380
+ */
3381
+ print() {
3382
+ console.log(this.toVisual());
3383
+ }
3384
+ };
3385
+
1989
3386
  // src/data-structures/linked-list/skip-linked-list.ts
1990
3387
  var SkipListNode = class {
1991
3388
  static {
@@ -1997,136 +3394,1033 @@ var SkipListNode = class {
1997
3394
  constructor(key, value, level) {
1998
3395
  this.key = key;
1999
3396
  this.value = value;
2000
- this.forward = new Array(level);
3397
+ this.forward = new Array(level).fill(void 0);
2001
3398
  }
2002
3399
  };
2003
- var SkipList = class {
3400
+ var SkipList = class _SkipList extends IterableEntryBase {
2004
3401
  static {
2005
3402
  __name(this, "SkipList");
2006
3403
  }
2007
- constructor(elements = [], options) {
2008
- if (options) {
2009
- const { maxLevel, probability } = options;
2010
- if (typeof maxLevel === "number") this._maxLevel = maxLevel;
2011
- if (typeof probability === "number") this._probability = probability;
2012
- }
2013
- if (elements) {
2014
- for (const [key, value] of elements) this.add(key, value);
3404
+ #comparator;
3405
+ #isDefaultComparator;
3406
+ constructor(entries = [], options = {}) {
3407
+ super();
3408
+ const { comparator, toEntryFn, maxLevel, probability } = options;
3409
+ if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
3410
+ if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
3411
+ this.#isDefaultComparator = comparator === void 0;
3412
+ this.#comparator = comparator ?? _SkipList.createDefaultComparator();
3413
+ this._head = new SkipListNode(void 0, void 0, this._maxLevel);
3414
+ for (const item of entries) {
3415
+ let k;
3416
+ let v;
3417
+ if (toEntryFn) {
3418
+ [k, v] = toEntryFn(item);
3419
+ } else {
3420
+ if (!Array.isArray(item) || item.length < 2) {
3421
+ throw new TypeError(ERR.invalidEntry("SkipList"));
3422
+ }
3423
+ [k, v] = item;
3424
+ }
3425
+ this.set(k, v);
2015
3426
  }
2016
3427
  }
2017
- _head = new SkipListNode(void 0, void 0, this.maxLevel);
2018
- get head() {
2019
- return this._head;
3428
+ /**
3429
+ * Creates a default comparator supporting number, string, Date, and bigint.
3430
+ */
3431
+ static createDefaultComparator() {
3432
+ return (a, b) => {
3433
+ if (typeof a === "number" && typeof b === "number") {
3434
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
3435
+ return a - b;
3436
+ }
3437
+ if (typeof a === "string" && typeof b === "string") {
3438
+ return a < b ? -1 : a > b ? 1 : 0;
3439
+ }
3440
+ if (a instanceof Date && b instanceof Date) {
3441
+ const ta = a.getTime(), tb = b.getTime();
3442
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
3443
+ return ta - tb;
3444
+ }
3445
+ if (typeof a === "bigint" && typeof b === "bigint") {
3446
+ return a < b ? -1 : a > b ? 1 : 0;
3447
+ }
3448
+ throw new TypeError(ERR.comparatorRequired("SkipList"));
3449
+ };
2020
3450
  }
3451
+ // ─── Internal state ──────────────────────────────────────────
3452
+ _head;
2021
3453
  _level = 0;
2022
- get level() {
2023
- return this._level;
2024
- }
3454
+ _size = 0;
2025
3455
  _maxLevel = 16;
3456
+ _probability = 0.5;
3457
+ // ─── Size & lifecycle ────────────────────────────────────────
3458
+ get size() {
3459
+ return this._size;
3460
+ }
2026
3461
  get maxLevel() {
2027
3462
  return this._maxLevel;
2028
3463
  }
2029
- _probability = 0.5;
2030
3464
  get probability() {
2031
3465
  return this._probability;
2032
3466
  }
2033
- get first() {
2034
- const firstNode = this.head.forward[0];
2035
- return firstNode ? firstNode.value : void 0;
3467
+ get comparator() {
3468
+ return this.#comparator;
2036
3469
  }
2037
- get last() {
2038
- let current = this.head;
2039
- for (let i = this.level - 1; i >= 0; i--) {
2040
- while (current.forward[i]) {
2041
- current = current.forward[i];
2042
- }
2043
- }
2044
- return current.value;
3470
+ /**
3471
+ * Check if empty
3472
+
3473
+
3474
+
3475
+
3476
+
3477
+
3478
+
3479
+
3480
+
3481
+
3482
+
3483
+
3484
+
3485
+
3486
+
3487
+
3488
+
3489
+
3490
+
3491
+
3492
+
3493
+
3494
+
3495
+
3496
+
3497
+
3498
+
3499
+
3500
+
3501
+ * @example
3502
+ * // Check if empty
3503
+ * const sl = new SkipList<number, string>();
3504
+ * console.log(sl.isEmpty()); // true;
3505
+ */
3506
+ isEmpty() {
3507
+ return this._size === 0;
2045
3508
  }
2046
- add(key, value) {
2047
- const newNode = new SkipListNode(key, value, this._randomLevel());
2048
- const update = new Array(this.maxLevel).fill(this.head);
2049
- let current = this.head;
2050
- for (let i = this.level - 1; i >= 0; i--) {
2051
- while (current.forward[i] && current.forward[i].key < key) {
2052
- current = current.forward[i];
3509
+ /**
3510
+ * Remove all entries
3511
+
3512
+
3513
+
3514
+
3515
+
3516
+
3517
+
3518
+
3519
+
3520
+
3521
+
3522
+
3523
+
3524
+
3525
+
3526
+
3527
+
3528
+
3529
+
3530
+
3531
+
3532
+
3533
+
3534
+
3535
+
3536
+
3537
+
3538
+
3539
+
3540
+ * @example
3541
+ * // Remove all entries
3542
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
3543
+ * sl.clear();
3544
+ * console.log(sl.isEmpty()); // true;
3545
+ */
3546
+ clear() {
3547
+ this._head = new SkipListNode(void 0, void 0, this._maxLevel);
3548
+ this._level = 0;
3549
+ this._size = 0;
3550
+ }
3551
+ /**
3552
+ * Create independent copy
3553
+
3554
+
3555
+
3556
+
3557
+
3558
+
3559
+
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+
3566
+
3567
+
3568
+
3569
+
3570
+
3571
+
3572
+
3573
+
3574
+
3575
+
3576
+
3577
+
3578
+
3579
+
3580
+
3581
+
3582
+ * @example
3583
+ * // Create independent copy
3584
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
3585
+ * const copy = sl.clone();
3586
+ * copy.delete(1);
3587
+ * console.log(sl.has(1)); // true;
3588
+ */
3589
+ clone() {
3590
+ return new _SkipList(this, {
3591
+ comparator: this.#isDefaultComparator ? void 0 : this.#comparator,
3592
+ maxLevel: this._maxLevel,
3593
+ probability: this._probability
3594
+ });
3595
+ }
3596
+ // ─── Core CRUD ───────────────────────────────────────────────
3597
+ /**
3598
+ * Insert or update a key-value pair. Returns `this` for chaining.
3599
+ * Unique keys only — if key exists, value is updated in place.
3600
+
3601
+
3602
+
3603
+
3604
+
3605
+
3606
+
3607
+
3608
+
3609
+
3610
+
3611
+
3612
+
3613
+
3614
+
3615
+
3616
+
3617
+
3618
+
3619
+
3620
+
3621
+
3622
+
3623
+
3624
+
3625
+
3626
+
3627
+
3628
+
3629
+
3630
+
3631
+
3632
+ * @example
3633
+ * // In-memory sorted key-value store
3634
+ * const store = new SkipList<number, string>();
3635
+ *
3636
+ * store.set(3, 'three');
3637
+ * store.set(1, 'one');
3638
+ * store.set(5, 'five');
3639
+ * store.set(2, 'two');
3640
+ *
3641
+ * console.log(store.get(3)); // 'three';
3642
+ * console.log(store.get(1)); // 'one';
3643
+ * console.log(store.get(5)); // 'five';
3644
+ *
3645
+ * // Update existing key
3646
+ * store.set(3, 'THREE');
3647
+ * console.log(store.get(3)); // 'THREE';
3648
+ */
3649
+ set(key, value) {
3650
+ const cmp = this.#comparator;
3651
+ const update = this._findUpdate(key);
3652
+ const existing = update[0].forward[0];
3653
+ if (existing && cmp(existing.key, key) === 0) {
3654
+ existing.value = value;
3655
+ return this;
3656
+ }
3657
+ const newLevel = this._randomLevel();
3658
+ const newNode = new SkipListNode(key, value, newLevel);
3659
+ if (newLevel > this._level) {
3660
+ for (let i = this._level; i < newLevel; i++) {
3661
+ update[i] = this._head;
2053
3662
  }
2054
- update[i] = current;
3663
+ this._level = newLevel;
2055
3664
  }
2056
- for (let i = 0; i < newNode.forward.length; i++) {
3665
+ for (let i = 0; i < newLevel; i++) {
2057
3666
  newNode.forward[i] = update[i].forward[i];
2058
3667
  update[i].forward[i] = newNode;
2059
3668
  }
2060
- if (!newNode.forward[0]) {
2061
- this._level = Math.max(this.level, newNode.forward.length);
2062
- }
3669
+ this._size++;
3670
+ return this;
2063
3671
  }
3672
+ /**
3673
+ * Get the value for a key, or `undefined` if not found.
3674
+ * Overrides base O(n) with O(log n) skip-list search.
3675
+
3676
+
3677
+
3678
+
3679
+
3680
+
3681
+
3682
+
3683
+
3684
+
3685
+
3686
+
3687
+
3688
+
3689
+
3690
+
3691
+
3692
+
3693
+
3694
+
3695
+
3696
+
3697
+
3698
+
3699
+
3700
+
3701
+
3702
+
3703
+
3704
+
3705
+
3706
+
3707
+ * @example
3708
+ * // Building a sorted index
3709
+ * type Product = { id: number; name: string; price: number };
3710
+ * const products: Product[] = [
3711
+ * { id: 1, name: 'Widget', price: 25 },
3712
+ * { id: 2, name: 'Gadget', price: 50 },
3713
+ * { id: 3, name: 'Doohickey', price: 15 }
3714
+ * ];
3715
+ *
3716
+ * const index = new SkipList<number, Product, Product>(products, {
3717
+ * toEntryFn: (p: Product) => [p.price, p]
3718
+ * });
3719
+ *
3720
+ * // Iterate in sorted order by price
3721
+ * const names = [...index.values()].map(p => p!.name);
3722
+ * console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
3723
+ *
3724
+ * // Range search: products between $20 and $60
3725
+ * const range = index.rangeSearch([20, 60]);
3726
+ * console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
3727
+ */
2064
3728
  get(key) {
2065
- let current = this.head;
2066
- for (let i = this.level - 1; i >= 0; i--) {
2067
- while (current.forward[i] && current.forward[i].key < key) {
2068
- current = current.forward[i];
2069
- }
2070
- }
2071
- current = current.forward[0];
2072
- if (current && current.key === key) {
2073
- return current.value;
2074
- }
2075
- return void 0;
3729
+ const node = this._findNode(key);
3730
+ return node ? node.value : void 0;
2076
3731
  }
3732
+ /**
3733
+ * Check if a key exists.
3734
+ * Overrides base O(n) with O(log n) skip-list search.
3735
+
3736
+
3737
+
3738
+
3739
+
3740
+
3741
+
3742
+
3743
+
3744
+
3745
+
3746
+
3747
+
3748
+
3749
+
3750
+
3751
+
3752
+
3753
+
3754
+
3755
+
3756
+
3757
+
3758
+
3759
+
3760
+
3761
+
3762
+
3763
+
3764
+
3765
+
3766
+
3767
+ * @example
3768
+ * // Check key existence
3769
+ * const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
3770
+ * console.log(sl.has(3)); // true;
3771
+ * console.log(sl.has(4)); // false;
3772
+ */
2077
3773
  has(key) {
2078
- return this.get(key) !== void 0;
3774
+ return this._findNode(key) !== void 0;
2079
3775
  }
3776
+ /**
3777
+ * Delete a key. Returns `true` if the key was found and removed.
3778
+
3779
+
3780
+
3781
+
3782
+
3783
+
3784
+
3785
+
3786
+
3787
+
3788
+
3789
+
3790
+
3791
+
3792
+
3793
+
3794
+
3795
+
3796
+
3797
+
3798
+
3799
+
3800
+
3801
+
3802
+
3803
+
3804
+
3805
+
3806
+
3807
+
3808
+
3809
+
3810
+ * @example
3811
+ * // Fast lookup with deletion
3812
+ * const cache = new SkipList<string, number>();
3813
+ *
3814
+ * cache.set('alpha', 1);
3815
+ * cache.set('beta', 2);
3816
+ * cache.set('gamma', 3);
3817
+ *
3818
+ * console.log(cache.has('beta')); // true;
3819
+ * cache.delete('beta');
3820
+ * console.log(cache.has('beta')); // false;
3821
+ * console.log(cache.size); // 2;
3822
+ */
2080
3823
  delete(key) {
2081
- const update = new Array(this.maxLevel).fill(this.head);
2082
- let current = this.head;
2083
- for (let i = this.level - 1; i >= 0; i--) {
2084
- while (current.forward[i] && current.forward[i].key < key) {
3824
+ const cmp = this.#comparator;
3825
+ const update = this._findUpdate(key);
3826
+ const target = update[0].forward[0];
3827
+ if (!target || cmp(target.key, key) !== 0) return false;
3828
+ for (let i = 0; i < this._level; i++) {
3829
+ if (update[i].forward[i] !== target) break;
3830
+ update[i].forward[i] = target.forward[i];
3831
+ }
3832
+ while (this._level > 0 && !this._head.forward[this._level - 1]) {
3833
+ this._level--;
3834
+ }
3835
+ this._size--;
3836
+ return true;
3837
+ }
3838
+ // ─── Navigation ──────────────────────────────────────────────
3839
+ /**
3840
+ * Returns the first (smallest key) entry, or `undefined` if empty.
3841
+
3842
+
3843
+
3844
+
3845
+
3846
+
3847
+
3848
+
3849
+
3850
+
3851
+
3852
+
3853
+
3854
+
3855
+
3856
+
3857
+
3858
+
3859
+
3860
+
3861
+
3862
+
3863
+
3864
+
3865
+
3866
+
3867
+
3868
+
3869
+
3870
+
3871
+
3872
+
3873
+ * @example
3874
+ * // Access the minimum entry
3875
+ * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
3876
+ * console.log(sl.first()); // [1, 'a'];
3877
+ */
3878
+ first() {
3879
+ const node = this._head.forward[0];
3880
+ return node ? [node.key, node.value] : void 0;
3881
+ }
3882
+ /**
3883
+ * Returns the last (largest key) entry, or `undefined` if empty.
3884
+
3885
+
3886
+
3887
+
3888
+
3889
+
3890
+
3891
+
3892
+
3893
+
3894
+
3895
+
3896
+
3897
+
3898
+
3899
+
3900
+
3901
+
3902
+
3903
+
3904
+
3905
+
3906
+
3907
+
3908
+
3909
+
3910
+
3911
+
3912
+
3913
+
3914
+
3915
+
3916
+ * @example
3917
+ * // Access the maximum entry
3918
+ * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
3919
+ * console.log(sl.last()); // [5, 'e'];
3920
+ */
3921
+ last() {
3922
+ let current = this._head;
3923
+ for (let i = this._level - 1; i >= 0; i--) {
3924
+ while (current.forward[i]) {
2085
3925
  current = current.forward[i];
2086
3926
  }
2087
- update[i] = current;
2088
3927
  }
2089
- current = current.forward[0];
2090
- if (current && current.key === key) {
2091
- for (let i = 0; i < this.level; i++) {
2092
- if (update[i].forward[i] !== current) {
2093
- break;
2094
- }
2095
- update[i].forward[i] = current.forward[i];
3928
+ return current === this._head ? void 0 : [current.key, current.value];
3929
+ }
3930
+ /**
3931
+ * Remove and return the first (smallest key) entry.
3932
+
3933
+
3934
+
3935
+
3936
+
3937
+
3938
+
3939
+
3940
+
3941
+
3942
+
3943
+
3944
+
3945
+
3946
+
3947
+
3948
+
3949
+
3950
+
3951
+
3952
+
3953
+
3954
+
3955
+
3956
+
3957
+
3958
+
3959
+
3960
+
3961
+ * @example
3962
+ * // Remove and return smallest
3963
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
3964
+ * console.log(sl.pollFirst()); // [1, 'a'];
3965
+ * console.log(sl.size); // 2;
3966
+ */
3967
+ pollFirst() {
3968
+ const entry = this.first();
3969
+ if (!entry) return void 0;
3970
+ this.delete(entry[0]);
3971
+ return entry;
3972
+ }
3973
+ /**
3974
+ * Remove and return the last (largest key) entry.
3975
+
3976
+
3977
+
3978
+
3979
+
3980
+
3981
+
3982
+
3983
+
3984
+
3985
+
3986
+
3987
+
3988
+
3989
+
3990
+
3991
+
3992
+
3993
+
3994
+
3995
+
3996
+
3997
+
3998
+
3999
+
4000
+
4001
+
4002
+
4003
+
4004
+ * @example
4005
+ * // Remove and return largest
4006
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
4007
+ * console.log(sl.pollLast()); // [3, 'c'];
4008
+ * console.log(sl.size); // 2;
4009
+ */
4010
+ pollLast() {
4011
+ const entry = this.last();
4012
+ if (!entry) return void 0;
4013
+ this.delete(entry[0]);
4014
+ return entry;
4015
+ }
4016
+ /**
4017
+ * Least entry ≥ key, or `undefined`.
4018
+
4019
+
4020
+
4021
+
4022
+
4023
+
4024
+
4025
+
4026
+
4027
+
4028
+
4029
+
4030
+
4031
+
4032
+
4033
+
4034
+
4035
+
4036
+
4037
+
4038
+
4039
+
4040
+
4041
+
4042
+
4043
+
4044
+
4045
+
4046
+
4047
+
4048
+
4049
+
4050
+ * @example
4051
+ * // Least entry ≥ key
4052
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
4053
+ * console.log(sl.ceiling(15)); // [20, 'b'];
4054
+ * console.log(sl.ceiling(20)); // [20, 'b'];
4055
+ */
4056
+ ceiling(key) {
4057
+ const cmp = this.#comparator;
4058
+ let current = this._head;
4059
+ for (let i = this._level - 1; i >= 0; i--) {
4060
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
4061
+ current = current.forward[i];
2096
4062
  }
2097
- while (this.level > 0 && !this.head.forward[this.level - 1]) {
2098
- this._level--;
4063
+ }
4064
+ const node = current.forward[0];
4065
+ return node ? [node.key, node.value] : void 0;
4066
+ }
4067
+ /**
4068
+ * Greatest entry ≤ key, or `undefined`.
4069
+
4070
+
4071
+
4072
+
4073
+
4074
+
4075
+
4076
+
4077
+
4078
+
4079
+
4080
+
4081
+
4082
+
4083
+
4084
+
4085
+
4086
+
4087
+
4088
+
4089
+
4090
+
4091
+
4092
+
4093
+
4094
+
4095
+
4096
+
4097
+
4098
+
4099
+
4100
+
4101
+ * @example
4102
+ * // Greatest entry ≤ key
4103
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
4104
+ * console.log(sl.floor(25)); // [20, 'b'];
4105
+ * console.log(sl.floor(5)); // undefined;
4106
+ */
4107
+ floor(key) {
4108
+ const cmp = this.#comparator;
4109
+ let current = this._head;
4110
+ for (let i = this._level - 1; i >= 0; i--) {
4111
+ while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
4112
+ current = current.forward[i];
2099
4113
  }
2100
- return true;
2101
4114
  }
2102
- return false;
4115
+ const result = current === this._head ? void 0 : current;
4116
+ if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
4117
+ return void 0;
2103
4118
  }
4119
+ /**
4120
+ * Least entry strictly > key, or `undefined`.
4121
+
4122
+
4123
+
4124
+
4125
+
4126
+
4127
+
4128
+
4129
+
4130
+
4131
+
4132
+
4133
+
4134
+
4135
+
4136
+
4137
+
4138
+
4139
+
4140
+
4141
+
4142
+
4143
+
4144
+
4145
+
4146
+
4147
+
4148
+
4149
+
4150
+ * @example
4151
+ * // Strictly greater entry
4152
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
4153
+ * console.log(sl.higher(15)); // [20, 'b'];
4154
+ * console.log(sl.higher(30)); // undefined;
4155
+ */
2104
4156
  higher(key) {
2105
- let current = this.head;
2106
- for (let i = this.level - 1; i >= 0; i--) {
2107
- while (current.forward[i] && current.forward[i].key <= key) {
4157
+ const cmp = this.#comparator;
4158
+ let current = this._head;
4159
+ for (let i = this._level - 1; i >= 0; i--) {
4160
+ while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
2108
4161
  current = current.forward[i];
2109
4162
  }
2110
4163
  }
2111
- const nextNode = current.forward[0];
2112
- return nextNode ? nextNode.value : void 0;
4164
+ const node = current.forward[0];
4165
+ return node ? [node.key, node.value] : void 0;
2113
4166
  }
4167
+ /**
4168
+ * Greatest entry strictly < key, or `undefined`.
4169
+
4170
+
4171
+
4172
+
4173
+
4174
+
4175
+
4176
+
4177
+
4178
+
4179
+
4180
+
4181
+
4182
+
4183
+
4184
+
4185
+
4186
+
4187
+
4188
+
4189
+
4190
+
4191
+
4192
+
4193
+
4194
+
4195
+
4196
+
4197
+
4198
+ * @example
4199
+ * // Strictly less entry
4200
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
4201
+ * console.log(sl.lower(25)); // [20, 'b'];
4202
+ * console.log(sl.lower(10)); // undefined;
4203
+ */
2114
4204
  lower(key) {
2115
- let current = this.head;
2116
- let lastLess = void 0;
2117
- for (let i = this.level - 1; i >= 0; i--) {
2118
- while (current.forward[i] && current.forward[i].key < key) {
4205
+ const cmp = this.#comparator;
4206
+ let current = this._head;
4207
+ let result;
4208
+ for (let i = this._level - 1; i >= 0; i--) {
4209
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
4210
+ current = current.forward[i];
4211
+ }
4212
+ if (current !== this._head && cmp(current.key, key) < 0) {
4213
+ result = current;
4214
+ }
4215
+ }
4216
+ return result ? [result.key, result.value] : void 0;
4217
+ }
4218
+ /**
4219
+ * Returns entries within the given key range.
4220
+
4221
+
4222
+
4223
+
4224
+
4225
+
4226
+
4227
+
4228
+
4229
+
4230
+
4231
+
4232
+
4233
+
4234
+
4235
+
4236
+
4237
+
4238
+
4239
+
4240
+
4241
+
4242
+
4243
+
4244
+
4245
+
4246
+
4247
+
4248
+
4249
+
4250
+
4251
+
4252
+ * @example
4253
+ * // Find entries in a range
4254
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
4255
+ * const result = sl.rangeSearch([2, 4]);
4256
+ * console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
4257
+ */
4258
+ rangeSearch(range, options = {}) {
4259
+ const { lowInclusive = true, highInclusive = true } = options;
4260
+ const [low, high] = range;
4261
+ const cmp = this.#comparator;
4262
+ const out = [];
4263
+ let current = this._head;
4264
+ for (let i = this._level - 1; i >= 0; i--) {
4265
+ while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
4266
+ current = current.forward[i];
4267
+ }
4268
+ }
4269
+ current = current.forward[0];
4270
+ while (current) {
4271
+ const cmpHigh = cmp(current.key, high);
4272
+ if (cmpHigh > 0) break;
4273
+ if (cmpHigh === 0 && !highInclusive) break;
4274
+ const cmpLow = cmp(current.key, low);
4275
+ if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
4276
+ out.push([current.key, current.value]);
4277
+ }
4278
+ current = current.forward[0];
4279
+ }
4280
+ return out;
4281
+ }
4282
+ // ─── Functional (overrides) ──────────────────────────────────
4283
+ /**
4284
+ * Creates a new SkipList with entries transformed by callback.
4285
+
4286
+
4287
+
4288
+
4289
+
4290
+
4291
+
4292
+
4293
+
4294
+
4295
+
4296
+
4297
+
4298
+
4299
+
4300
+
4301
+
4302
+
4303
+
4304
+
4305
+
4306
+
4307
+
4308
+
4309
+
4310
+
4311
+
4312
+
4313
+
4314
+ * @example
4315
+ * // Transform entries
4316
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
4317
+ * const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
4318
+ * console.log([...mapped.values()]); // ['A', 'B'];
4319
+ */
4320
+ map(callback, options) {
4321
+ const out = new _SkipList([], options ?? {});
4322
+ let i = 0;
4323
+ for (const [k, v] of this) {
4324
+ const [nk, nv] = callback(v, k, i++, this);
4325
+ out.set(nk, nv);
4326
+ }
4327
+ return out;
4328
+ }
4329
+ /**
4330
+ * Creates a new SkipList with entries that pass the predicate.
4331
+
4332
+
4333
+
4334
+
4335
+
4336
+
4337
+
4338
+
4339
+
4340
+
4341
+
4342
+
4343
+
4344
+
4345
+
4346
+
4347
+
4348
+
4349
+
4350
+
4351
+
4352
+
4353
+
4354
+
4355
+
4356
+
4357
+
4358
+
4359
+
4360
+ * @example
4361
+ * // Filter entries
4362
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
4363
+ * const result = sl.filter((v, k) => k > 1);
4364
+ * console.log(result.size); // 2;
4365
+ */
4366
+ filter(callbackfn, thisArg) {
4367
+ const out = new _SkipList([], {
4368
+ comparator: this.#isDefaultComparator ? void 0 : this.#comparator,
4369
+ maxLevel: this._maxLevel,
4370
+ probability: this._probability
4371
+ });
4372
+ let i = 0;
4373
+ for (const [k, v] of this) {
4374
+ const ok = callbackfn.call(thisArg, v, k, i++, this);
4375
+ if (ok) out.set(k, v);
4376
+ }
4377
+ return out;
4378
+ }
4379
+ // ─── Iterator (required by IterableEntryBase) ────────────────
4380
+ _getIterator() {
4381
+ const head = this._head;
4382
+ return (function* () {
4383
+ let node = head.forward[0];
4384
+ while (node) {
4385
+ yield [node.key, node.value];
4386
+ node = node.forward[0];
4387
+ }
4388
+ })();
4389
+ }
4390
+ // ─── Internal helpers ────────────────────────────────────────
4391
+ /**
4392
+ * Finds the update array (predecessors at each level) for a given key.
4393
+ */
4394
+ _findUpdate(key) {
4395
+ const cmp = this.#comparator;
4396
+ const update = new Array(this._maxLevel).fill(this._head);
4397
+ let current = this._head;
4398
+ for (let i = this._level - 1; i >= 0; i--) {
4399
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
2119
4400
  current = current.forward[i];
2120
4401
  }
2121
- if (current.key < key) {
2122
- lastLess = current;
4402
+ update[i] = current;
4403
+ }
4404
+ return update;
4405
+ }
4406
+ /**
4407
+ * Finds the node for a given key, or undefined.
4408
+ */
4409
+ _findNode(key) {
4410
+ const cmp = this.#comparator;
4411
+ let current = this._head;
4412
+ for (let i = this._level - 1; i >= 0; i--) {
4413
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
4414
+ current = current.forward[i];
2123
4415
  }
2124
4416
  }
2125
- return lastLess ? lastLess.value : void 0;
4417
+ const candidate = current.forward[0];
4418
+ if (candidate && cmp(candidate.key, key) === 0) return candidate;
4419
+ return void 0;
2126
4420
  }
2127
4421
  _randomLevel() {
2128
4422
  let level = 1;
2129
- while (Math.random() < this.probability && level < this.maxLevel) {
4423
+ while (Math.random() < this._probability && level < this._maxLevel) {
2130
4424
  level++;
2131
4425
  }
2132
4426
  return level;