linked-list-typed 2.4.5 → 2.5.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 (76) hide show
  1. package/README.md +14 -50
  2. package/dist/cjs/index.cjs +1538 -294
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs-legacy/index.cjs +1544 -291
  5. package/dist/cjs-legacy/index.cjs.map +1 -1
  6. package/dist/esm/index.mjs +1538 -294
  7. package/dist/esm/index.mjs.map +1 -1
  8. package/dist/esm-legacy/index.mjs +1544 -291
  9. package/dist/esm-legacy/index.mjs.map +1 -1
  10. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  11. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  12. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  13. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +429 -78
  14. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  15. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +212 -32
  16. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  17. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  18. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  19. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  20. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  21. package/dist/types/data-structures/graph/directed-graph.d.ts +219 -47
  22. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  23. package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -59
  24. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  25. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  26. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  27. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  28. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  29. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  30. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  31. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  32. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  33. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  34. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  35. package/dist/types/data-structures/queue/deque.d.ts +272 -65
  36. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  37. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  38. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  39. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  40. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  41. package/dist/umd/linked-list-typed.js +1541 -289
  42. package/dist/umd/linked-list-typed.js.map +1 -1
  43. package/dist/umd/linked-list-typed.min.js +1 -1
  44. package/dist/umd/linked-list-typed.min.js.map +1 -1
  45. package/package.json +2 -2
  46. package/src/data-structures/base/iterable-element-base.ts +4 -5
  47. package/src/data-structures/binary-tree/avl-tree.ts +134 -51
  48. package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
  49. package/src/data-structures/binary-tree/binary-tree.ts +429 -79
  50. package/src/data-structures/binary-tree/bst.ts +335 -34
  51. package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
  52. package/src/data-structures/binary-tree/segment-tree.ts +372 -248
  53. package/src/data-structures/binary-tree/tree-map.ts +1284 -6
  54. package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
  55. package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
  56. package/src/data-structures/binary-tree/tree-set.ts +1136 -9
  57. package/src/data-structures/graph/directed-graph.ts +219 -47
  58. package/src/data-structures/graph/map-graph.ts +59 -1
  59. package/src/data-structures/graph/undirected-graph.ts +204 -59
  60. package/src/data-structures/hash/hash-map.ts +230 -77
  61. package/src/data-structures/heap/heap.ts +287 -99
  62. package/src/data-structures/heap/max-heap.ts +46 -0
  63. package/src/data-structures/heap/min-heap.ts +59 -0
  64. package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
  65. package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
  66. package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
  67. package/src/data-structures/matrix/matrix.ts +416 -12
  68. package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
  69. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  70. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  71. package/src/data-structures/queue/deque.ts +272 -65
  72. package/src/data-structures/queue/queue.ts +211 -42
  73. package/src/data-structures/stack/stack.ts +174 -32
  74. package/src/data-structures/trie/trie.ts +213 -43
  75. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  76. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
@@ -1,55 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
- // src/common/error.ts
5
- var ERR = {
6
- // Range / index
7
- indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
8
- invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
9
- // Type / argument
10
- invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
11
- comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
12
- invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
13
- notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
14
- invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
15
- invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
16
- invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
17
- reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
18
- callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
19
- // State / operation
20
- invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
21
- // Matrix
22
- matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
23
- matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
24
- matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
25
- matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
26
- matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
27
- };
28
-
29
- // src/common/index.ts
30
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
31
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
32
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
33
- return DFSOperation2;
34
- })(DFSOperation || {});
35
- var Range = class {
36
- constructor(low, high, includeLow = true, includeHigh = true) {
37
- this.low = low;
38
- this.high = high;
39
- this.includeLow = includeLow;
40
- this.includeHigh = includeHigh;
41
- }
42
- static {
43
- __name(this, "Range");
44
- }
45
- // Determine whether a key is within the range
46
- isInRange(key, comparator) {
47
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
48
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
49
- return lowCheck && highCheck;
50
- }
51
- };
52
-
53
4
  // src/data-structures/base/iterable-element-base.ts
54
5
  var IterableElementBase = class {
55
6
  static {
@@ -68,7 +19,7 @@ var IterableElementBase = class {
68
19
  if (options) {
69
20
  const { toElementFn } = options;
70
21
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
71
- else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
22
+ else if (toElementFn) throw new TypeError("toElementFn must be a function type");
72
23
  }
73
24
  }
74
25
  /**
@@ -231,7 +182,7 @@ var IterableElementBase = class {
231
182
  acc = initialValue;
232
183
  } else {
233
184
  const first = iter.next();
234
- if (first.done) throw new TypeError(ERR.reduceEmpty());
185
+ if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
235
186
  acc = first.value;
236
187
  index = 1;
237
188
  }
@@ -772,11 +723,37 @@ var SinglyLinkedList = class extends LinearLinkedBase {
772
723
  return list;
773
724
  }
774
725
  /**
775
- * Append an element/node to the tail.
776
- * @remarks Time O(1), Space O(1)
777
- * @param elementOrNode - Element or node to append.
778
- * @returns True when appended.
779
- */
726
+ * Append an element/node to the tail.
727
+ * @remarks Time O(1), Space O(1)
728
+ * @param elementOrNode - Element or node to append.
729
+ * @returns True when appended.
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+ * @example
742
+ * // basic SinglyLinkedList creation and push operation
743
+ * // Create a simple SinglyLinkedList with initial values
744
+ * const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
745
+ *
746
+ * // Verify the list maintains insertion order
747
+ * console.log([...list]); // [1, 2, 3, 4, 5];
748
+ *
749
+ * // Check length
750
+ * console.log(list.length); // 5;
751
+ *
752
+ * // Push a new element to the end
753
+ * list.push(6);
754
+ * console.log(list.length); // 6;
755
+ * console.log([...list]); // [1, 2, 3, 4, 5, 6];
756
+ */
780
757
  push(elementOrNode) {
781
758
  const newNode = this._ensureNode(elementOrNode);
782
759
  if (!this.head) {
@@ -790,10 +767,36 @@ var SinglyLinkedList = class extends LinearLinkedBase {
790
767
  return true;
791
768
  }
792
769
  /**
793
- * Remove and return the tail element.
794
- * @remarks Time O(N), Space O(1)
795
- * @returns Removed element or undefined.
796
- */
770
+ * Remove and return the tail element.
771
+ * @remarks Time O(N), Space O(1)
772
+ * @returns Removed element or undefined.
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+ * @example
785
+ * // SinglyLinkedList pop and shift operations
786
+ * const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
787
+ *
788
+ * // Pop removes from the end
789
+ * const last = list.pop();
790
+ * console.log(last); // 50;
791
+ *
792
+ * // Shift removes from the beginning
793
+ * const first = list.shift();
794
+ * console.log(first); // 10;
795
+ *
796
+ * // Verify remaining elements
797
+ * console.log([...list]); // [20, 30, 40];
798
+ * console.log(list.length); // 3;
799
+ */
797
800
  pop() {
798
801
  if (!this.head) return void 0;
799
802
  if (this.head === this.tail) {
@@ -812,10 +815,26 @@ var SinglyLinkedList = class extends LinearLinkedBase {
812
815
  return value;
813
816
  }
814
817
  /**
815
- * Remove and return the head element.
816
- * @remarks Time O(1), Space O(1)
817
- * @returns Removed element or undefined.
818
- */
818
+ * Remove and return the head element.
819
+ * @remarks Time O(1), Space O(1)
820
+ * @returns Removed element or undefined.
821
+
822
+
823
+
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+ * @example
833
+ * // Remove from the front
834
+ * const list = new SinglyLinkedList<number>([10, 20, 30]);
835
+ * console.log(list.shift()); // 10;
836
+ * console.log(list.length); // 2;
837
+ */
819
838
  shift() {
820
839
  if (!this.head) return void 0;
821
840
  const removed = this.head;
@@ -825,11 +844,42 @@ var SinglyLinkedList = class extends LinearLinkedBase {
825
844
  return removed.value;
826
845
  }
827
846
  /**
828
- * Prepend an element/node to the head.
829
- * @remarks Time O(1), Space O(1)
830
- * @param elementOrNode - Element or node to prepend.
831
- * @returns True when prepended.
832
- */
847
+ * Prepend an element/node to the head.
848
+ * @remarks Time O(1), Space O(1)
849
+ * @param elementOrNode - Element or node to prepend.
850
+ * @returns True when prepended.
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+
862
+ * @example
863
+ * // SinglyLinkedList unshift and forward traversal
864
+ * const list = new SinglyLinkedList<number>([20, 30, 40]);
865
+ *
866
+ * // Unshift adds to the beginning
867
+ * list.unshift(10);
868
+ * console.log([...list]); // [10, 20, 30, 40];
869
+ *
870
+ * // Access elements (forward traversal only for singly linked)
871
+ * const second = list.at(1);
872
+ * console.log(second); // 20;
873
+ *
874
+ * // SinglyLinkedList allows forward iteration only
875
+ * const elements: number[] = [];
876
+ * for (const item of list) {
877
+ * elements.push(item);
878
+ * }
879
+ * console.log(elements); // [10, 20, 30, 40];
880
+ *
881
+ * console.log(list.length); // 4;
882
+ */
833
883
  unshift(elementOrNode) {
834
884
  const newNode = this._ensureNode(elementOrNode);
835
885
  if (!this.head) {
@@ -885,11 +935,28 @@ var SinglyLinkedList = class extends LinearLinkedBase {
885
935
  return void 0;
886
936
  }
887
937
  /**
888
- * Get the element at a given index.
889
- * @remarks Time O(N), Space O(1)
890
- * @param index - Zero-based index.
891
- * @returns Element or undefined.
892
- */
938
+ * Get the element at a given index.
939
+ * @remarks Time O(N), Space O(1)
940
+ * @param index - Zero-based index.
941
+ * @returns Element or undefined.
942
+
943
+
944
+
945
+
946
+
947
+
948
+
949
+
950
+
951
+
952
+
953
+ * @example
954
+ * // Access element by index
955
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
956
+ * console.log(list.at(0)); // 'a';
957
+ * console.log(list.at(2)); // 'c';
958
+ * console.log(list.at(3)); // 'd';
959
+ */
893
960
  at(index) {
894
961
  if (index < 0 || index >= this._length) return void 0;
895
962
  let current = this.head;
@@ -906,11 +973,23 @@ var SinglyLinkedList = class extends LinearLinkedBase {
906
973
  return elementNodeOrPredicate instanceof SinglyLinkedListNode;
907
974
  }
908
975
  /**
909
- * Get the node reference at a given index.
910
- * @remarks Time O(N), Space O(1)
911
- * @param index - Zero-based index.
912
- * @returns Node or undefined.
913
- */
976
+ * Get the node reference at a given index.
977
+ * @remarks Time O(N), Space O(1)
978
+ * @param index - Zero-based index.
979
+ * @returns Node or undefined.
980
+
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+ * @example
989
+ * // Get node at index
990
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
991
+ * console.log(list.getNodeAt(1)?.value); // 'b';
992
+ */
914
993
  getNodeAt(index) {
915
994
  if (index < 0 || index >= this._length) return void 0;
916
995
  let current = this.head;
@@ -918,11 +997,24 @@ var SinglyLinkedList = class extends LinearLinkedBase {
918
997
  return current;
919
998
  }
920
999
  /**
921
- * Delete the element at an index.
922
- * @remarks Time O(N), Space O(1)
923
- * @param index - Zero-based index.
924
- * @returns Removed element or undefined.
925
- */
1000
+ * Delete the element at an index.
1001
+ * @remarks Time O(N), Space O(1)
1002
+ * @param index - Zero-based index.
1003
+ * @returns Removed element or undefined.
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+ * @example
1013
+ * // Remove by index
1014
+ * const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
1015
+ * list.deleteAt(1);
1016
+ * console.log(list.toArray()); // ['a', 'c'];
1017
+ */
926
1018
  deleteAt(index) {
927
1019
  if (index < 0 || index >= this._length) return void 0;
928
1020
  if (index === 0) return this.shift();
@@ -935,11 +1027,24 @@ var SinglyLinkedList = class extends LinearLinkedBase {
935
1027
  return value;
936
1028
  }
937
1029
  /**
938
- * Delete the first match by value/node.
939
- * @remarks Time O(N), Space O(1)
940
- * @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
941
- * @returns True if removed.
942
- */
1030
+ * Delete the first match by value/node.
1031
+ * @remarks Time O(N), Space O(1)
1032
+ * @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
1033
+ * @returns True if removed.
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+ * @example
1043
+ * // Remove first occurrence
1044
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
1045
+ * list.delete(2);
1046
+ * console.log(list.toArray()); // [1, 3, 2];
1047
+ */
943
1048
  delete(elementOrNode) {
944
1049
  if (elementOrNode === void 0 || !this.head) return false;
945
1050
  const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
@@ -956,12 +1061,25 @@ var SinglyLinkedList = class extends LinearLinkedBase {
956
1061
  return true;
957
1062
  }
958
1063
  /**
959
- * Insert a new element/node at an index, shifting following nodes.
960
- * @remarks Time O(N), Space O(1)
961
- * @param index - Zero-based index.
962
- * @param newElementOrNode - Element or node to insert.
963
- * @returns True if inserted.
964
- */
1064
+ * Insert a new element/node at an index, shifting following nodes.
1065
+ * @remarks Time O(N), Space O(1)
1066
+ * @param index - Zero-based index.
1067
+ * @param newElementOrNode - Element or node to insert.
1068
+ * @returns True if inserted.
1069
+
1070
+
1071
+
1072
+
1073
+
1074
+
1075
+
1076
+
1077
+ * @example
1078
+ * // Insert at index
1079
+ * const list = new SinglyLinkedList<number>([1, 3]);
1080
+ * list.addAt(1, 2);
1081
+ * console.log(list.toArray()); // [1, 2, 3];
1082
+ */
965
1083
  addAt(index, newElementOrNode) {
966
1084
  if (index < 0 || index > this._length) return false;
967
1085
  if (index === 0) return this.unshift(newElementOrNode);
@@ -987,28 +1105,70 @@ var SinglyLinkedList = class extends LinearLinkedBase {
987
1105
  return true;
988
1106
  }
989
1107
  /**
990
- * Check whether the list is empty.
991
- * @remarks Time O(1), Space O(1)
992
- * @returns True if length is 0.
993
- */
1108
+ * Check whether the list is empty.
1109
+ * @remarks Time O(1), Space O(1)
1110
+ * @returns True if length is 0.
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+
1119
+
1120
+ * @example
1121
+ * // Check empty
1122
+ * console.log(new SinglyLinkedList().isEmpty()); // true;
1123
+ */
994
1124
  isEmpty() {
995
1125
  return this._length === 0;
996
1126
  }
997
1127
  /**
998
- * Remove all nodes and reset length.
999
- * @remarks Time O(N), Space O(1)
1000
- * @returns void
1001
- */
1128
+ * Remove all nodes and reset length.
1129
+ * @remarks Time O(N), Space O(1)
1130
+ * @returns void
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+
1140
+ * @example
1141
+ * // Remove all
1142
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1143
+ * list.clear();
1144
+ * console.log(list.isEmpty()); // true;
1145
+ */
1002
1146
  clear() {
1003
1147
  this._head = void 0;
1004
1148
  this._tail = void 0;
1005
1149
  this._length = 0;
1006
1150
  }
1007
1151
  /**
1008
- * Reverse the list in place.
1009
- * @remarks Time O(N), Space O(1)
1010
- * @returns This list.
1011
- */
1152
+ * Reverse the list in place.
1153
+ * @remarks Time O(N), Space O(1)
1154
+ * @returns This list.
1155
+
1156
+
1157
+
1158
+
1159
+
1160
+
1161
+
1162
+
1163
+
1164
+
1165
+
1166
+ * @example
1167
+ * // Reverse the list in-place
1168
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
1169
+ * list.reverse();
1170
+ * console.log([...list]); // [4, 3, 2, 1];
1171
+ */
1012
1172
  reverse() {
1013
1173
  if (!this.head || this.head === this.tail) return this;
1014
1174
  let prev;
@@ -1183,22 +1343,64 @@ var SinglyLinkedList = class extends LinearLinkedBase {
1183
1343
  return false;
1184
1344
  }
1185
1345
  /**
1186
- * Deep clone this list (values are copied by reference).
1187
- * @remarks Time O(N), Space O(N)
1188
- * @returns A new list with the same element sequence.
1189
- */
1346
+ * Deep clone this list (values are copied by reference).
1347
+ * @remarks Time O(N), Space O(N)
1348
+ * @returns A new list with the same element sequence.
1349
+
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+ * @example
1359
+ * // Deep copy
1360
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1361
+ * const copy = list.clone();
1362
+ * copy.pop();
1363
+ * console.log(list.length); // 3;
1364
+ * console.log(copy.length); // 2;
1365
+ */
1190
1366
  clone() {
1191
1367
  const out = this._createInstance();
1192
1368
  for (const v of this) out.push(v);
1193
1369
  return out;
1194
1370
  }
1195
1371
  /**
1196
- * Filter values into a new list of the same class.
1197
- * @remarks Time O(N), Space O(N)
1198
- * @param callback - Predicate (value, index, list) → boolean to keep value.
1199
- * @param [thisArg] - Value for `this` inside the callback.
1200
- * @returns A new list with kept values.
1201
- */
1372
+ * Filter values into a new list of the same class.
1373
+ * @remarks Time O(N), Space O(N)
1374
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
1375
+ * @param [thisArg] - Value for `this` inside the callback.
1376
+ * @returns A new list with kept values.
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+
1383
+
1384
+
1385
+
1386
+
1387
+
1388
+ * @example
1389
+ * // SinglyLinkedList filter and map operations
1390
+ * const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
1391
+ *
1392
+ * // Filter even numbers
1393
+ * const filtered = list.filter(value => value % 2 === 0);
1394
+ * console.log(filtered.length); // 2;
1395
+ *
1396
+ * // Map to double values
1397
+ * const doubled = list.map(value => value * 2);
1398
+ * console.log(doubled.length); // 5;
1399
+ *
1400
+ * // Use reduce to sum
1401
+ * const sum = list.reduce((acc, value) => acc + value, 0);
1402
+ * console.log(sum); // 15;
1403
+ */
1202
1404
  filter(callback, thisArg) {
1203
1405
  const out = this._createInstance();
1204
1406
  let index = 0;
@@ -1222,15 +1424,31 @@ var SinglyLinkedList = class extends LinearLinkedBase {
1222
1424
  return out;
1223
1425
  }
1224
1426
  /**
1225
- * Map values into a new list (possibly different element type).
1226
- * @remarks Time O(N), Space O(N)
1227
- * @template EM
1228
- * @template RM
1229
- * @param callback - Mapping function (value, index, list) → newElement.
1230
- * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1231
- * @param [thisArg] - Value for `this` inside the callback.
1232
- * @returns A new SinglyLinkedList with mapped values.
1233
- */
1427
+ * Map values into a new list (possibly different element type).
1428
+ * @remarks Time O(N), Space O(N)
1429
+ * @template EM
1430
+ * @template RM
1431
+ * @param callback - Mapping function (value, index, list) → newElement.
1432
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1433
+ * @param [thisArg] - Value for `this` inside the callback.
1434
+ * @returns A new SinglyLinkedList with mapped values.
1435
+
1436
+
1437
+
1438
+
1439
+
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+ * @example
1447
+ * // Transform elements
1448
+ * const list = new SinglyLinkedList<number>([1, 2, 3]);
1449
+ * const doubled = list.map(n => n * 2);
1450
+ * console.log([...doubled]); // [2, 4, 6];
1451
+ */
1234
1452
  map(callback, options, thisArg) {
1235
1453
  const out = this._createLike([], { ...options ?? {}, maxLen: this._maxLen });
1236
1454
  let index = 0;
@@ -1506,11 +1724,37 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1506
1724
  return elementNodeOrPredicate instanceof DoublyLinkedListNode;
1507
1725
  }
1508
1726
  /**
1509
- * Append an element/node to the tail.
1510
- * @remarks Time O(1), Space O(1)
1511
- * @param elementOrNode - Element or node to append.
1512
- * @returns True when appended.
1513
- */
1727
+ * Append an element/node to the tail.
1728
+ * @remarks Time O(1), Space O(1)
1729
+ * @param elementOrNode - Element or node to append.
1730
+ * @returns True when appended.
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+ * @example
1743
+ * // basic DoublyLinkedList creation and push operation
1744
+ * // Create a simple DoublyLinkedList with initial values
1745
+ * const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
1746
+ *
1747
+ * // Verify the list maintains insertion order
1748
+ * console.log([...list]); // [1, 2, 3, 4, 5];
1749
+ *
1750
+ * // Check length
1751
+ * console.log(list.length); // 5;
1752
+ *
1753
+ * // Push a new element to the end
1754
+ * list.push(6);
1755
+ * console.log(list.length); // 6;
1756
+ * console.log([...list]); // [1, 2, 3, 4, 5, 6];
1757
+ */
1514
1758
  push(elementOrNode) {
1515
1759
  const newNode = this._ensureNode(elementOrNode);
1516
1760
  if (!this.head) {
@@ -1526,10 +1770,36 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1526
1770
  return true;
1527
1771
  }
1528
1772
  /**
1529
- * Remove and return the tail element.
1530
- * @remarks Time O(1), Space O(1)
1531
- * @returns Removed element or undefined.
1532
- */
1773
+ * Remove and return the tail element.
1774
+ * @remarks Time O(1), Space O(1)
1775
+ * @returns Removed element or undefined.
1776
+
1777
+
1778
+
1779
+
1780
+
1781
+
1782
+
1783
+
1784
+
1785
+
1786
+
1787
+ * @example
1788
+ * // DoublyLinkedList pop and shift operations
1789
+ * const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
1790
+ *
1791
+ * // Pop removes from the end
1792
+ * const last = list.pop();
1793
+ * console.log(last); // 50;
1794
+ *
1795
+ * // Shift removes from the beginning
1796
+ * const first = list.shift();
1797
+ * console.log(first); // 10;
1798
+ *
1799
+ * // Verify remaining elements
1800
+ * console.log([...list]); // [20, 30, 40];
1801
+ * console.log(list.length); // 3;
1802
+ */
1533
1803
  pop() {
1534
1804
  if (!this.tail) return void 0;
1535
1805
  const removed = this.tail;
@@ -1544,10 +1814,26 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1544
1814
  return removed.value;
1545
1815
  }
1546
1816
  /**
1547
- * Remove and return the head element.
1548
- * @remarks Time O(1), Space O(1)
1549
- * @returns Removed element or undefined.
1550
- */
1817
+ * Remove and return the head element.
1818
+ * @remarks Time O(1), Space O(1)
1819
+ * @returns Removed element or undefined.
1820
+
1821
+
1822
+
1823
+
1824
+
1825
+
1826
+
1827
+
1828
+
1829
+
1830
+
1831
+ * @example
1832
+ * // Remove from the front
1833
+ * const list = new DoublyLinkedList<number>([10, 20, 30]);
1834
+ * console.log(list.shift()); // 10;
1835
+ * console.log(list.first); // 20;
1836
+ */
1551
1837
  shift() {
1552
1838
  if (!this.head) return void 0;
1553
1839
  const removed = this.head;
@@ -1562,11 +1848,27 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1562
1848
  return removed.value;
1563
1849
  }
1564
1850
  /**
1565
- * Prepend an element/node to the head.
1566
- * @remarks Time O(1), Space O(1)
1567
- * @param elementOrNode - Element or node to prepend.
1568
- * @returns True when prepended.
1569
- */
1851
+ * Prepend an element/node to the head.
1852
+ * @remarks Time O(1), Space O(1)
1853
+ * @param elementOrNode - Element or node to prepend.
1854
+ * @returns True when prepended.
1855
+
1856
+
1857
+
1858
+
1859
+
1860
+
1861
+
1862
+
1863
+
1864
+
1865
+
1866
+ * @example
1867
+ * // Add to the front
1868
+ * const list = new DoublyLinkedList<number>([2, 3]);
1869
+ * list.unshift(1);
1870
+ * console.log([...list]); // [1, 2, 3];
1871
+ */
1570
1872
  unshift(elementOrNode) {
1571
1873
  const newNode = this._ensureNode(elementOrNode);
1572
1874
  if (!this.head) {
@@ -1610,11 +1912,27 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1610
1912
  return ans;
1611
1913
  }
1612
1914
  /**
1613
- * Get the element at a given index.
1614
- * @remarks Time O(N), Space O(1)
1615
- * @param index - Zero-based index.
1616
- * @returns Element or undefined.
1617
- */
1915
+ * Get the element at a given index.
1916
+ * @remarks Time O(N), Space O(1)
1917
+ * @param index - Zero-based index.
1918
+ * @returns Element or undefined.
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+ * @example
1931
+ * // Access by index
1932
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
1933
+ * console.log(list.at(1)); // 'b';
1934
+ * console.log(list.at(2)); // 'c';
1935
+ */
1618
1936
  at(index) {
1619
1937
  if (index < 0 || index >= this._length) return void 0;
1620
1938
  let current = this.head;
@@ -1622,11 +1940,23 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1622
1940
  return current?.value;
1623
1941
  }
1624
1942
  /**
1625
- * Get the node reference at a given index.
1626
- * @remarks Time O(N), Space O(1)
1627
- * @param index - Zero-based index.
1628
- * @returns Node or undefined.
1629
- */
1943
+ * Get the node reference at a given index.
1944
+ * @remarks Time O(N), Space O(1)
1945
+ * @param index - Zero-based index.
1946
+ * @returns Node or undefined.
1947
+
1948
+
1949
+
1950
+
1951
+
1952
+
1953
+
1954
+
1955
+ * @example
1956
+ * // Get node at index
1957
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
1958
+ * console.log(list.getNodeAt(1)?.value); // 'b';
1959
+ */
1630
1960
  getNodeAt(index) {
1631
1961
  if (index < 0 || index >= this._length) return void 0;
1632
1962
  let current = this.head;
@@ -1665,12 +1995,25 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1665
1995
  return void 0;
1666
1996
  }
1667
1997
  /**
1668
- * Insert a new element/node at an index, shifting following nodes.
1669
- * @remarks Time O(N), Space O(1)
1670
- * @param index - Zero-based index.
1671
- * @param newElementOrNode - Element or node to insert.
1672
- * @returns True if inserted.
1673
- */
1998
+ * Insert a new element/node at an index, shifting following nodes.
1999
+ * @remarks Time O(N), Space O(1)
2000
+ * @param index - Zero-based index.
2001
+ * @param newElementOrNode - Element or node to insert.
2002
+ * @returns True if inserted.
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+
2009
+
2010
+
2011
+ * @example
2012
+ * // Insert at position
2013
+ * const list = new DoublyLinkedList<number>([1, 3]);
2014
+ * list.addAt(1, 2);
2015
+ * console.log(list.toArray()); // [1, 2, 3];
2016
+ */
1674
2017
  addAt(index, newElementOrNode) {
1675
2018
  if (index < 0 || index > this._length) return false;
1676
2019
  if (index === 0) return this.unshift(newElementOrNode);
@@ -1737,11 +2080,24 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1737
2080
  return true;
1738
2081
  }
1739
2082
  /**
1740
- * Delete the element at an index.
1741
- * @remarks Time O(N), Space O(1)
1742
- * @param index - Zero-based index.
1743
- * @returns Removed element or undefined.
1744
- */
2083
+ * Delete the element at an index.
2084
+ * @remarks Time O(N), Space O(1)
2085
+ * @param index - Zero-based index.
2086
+ * @returns Removed element or undefined.
2087
+
2088
+
2089
+
2090
+
2091
+
2092
+
2093
+
2094
+
2095
+ * @example
2096
+ * // Remove by index
2097
+ * const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
2098
+ * list.deleteAt(1);
2099
+ * console.log(list.toArray()); // ['a', 'c'];
2100
+ */
1745
2101
  deleteAt(index) {
1746
2102
  if (index < 0 || index >= this._length) return;
1747
2103
  if (index === 0) return this.shift();
@@ -1755,11 +2111,24 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1755
2111
  return removedNode.value;
1756
2112
  }
1757
2113
  /**
1758
- * Delete the first match by value/node.
1759
- * @remarks Time O(N), Space O(1)
1760
- * @param [elementOrNode] - Element or node to remove.
1761
- * @returns True if removed.
1762
- */
2114
+ * Delete the first match by value/node.
2115
+ * @remarks Time O(N), Space O(1)
2116
+ * @param [elementOrNode] - Element or node to remove.
2117
+ * @returns True if removed.
2118
+
2119
+
2120
+
2121
+
2122
+
2123
+
2124
+
2125
+
2126
+ * @example
2127
+ * // Remove first occurrence
2128
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
2129
+ * list.delete(2);
2130
+ * console.log(list.toArray()); // [1, 3, 2];
2131
+ */
1763
2132
  delete(elementOrNode) {
1764
2133
  const node = this.getNode(elementOrNode);
1765
2134
  if (!node) return false;
@@ -1775,29 +2144,68 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1775
2144
  return true;
1776
2145
  }
1777
2146
  /**
1778
- * Check whether the list is empty.
1779
- * @remarks Time O(1), Space O(1)
1780
- * @returns True if length is 0.
1781
- */
2147
+ * Check whether the list is empty.
2148
+ * @remarks Time O(1), Space O(1)
2149
+ * @returns True if length is 0.
2150
+
2151
+
2152
+
2153
+
2154
+
2155
+
2156
+
2157
+
2158
+
2159
+ * @example
2160
+ * // Check empty
2161
+ * console.log(new DoublyLinkedList().isEmpty()); // true;
2162
+ */
1782
2163
  isEmpty() {
1783
2164
  return this._length === 0;
1784
2165
  }
1785
2166
  /**
1786
- * Remove all nodes and reset length.
1787
- * @remarks Time O(N), Space O(1)
1788
- * @returns void
1789
- */
2167
+ * Remove all nodes and reset length.
2168
+ * @remarks Time O(N), Space O(1)
2169
+ * @returns void
2170
+
2171
+
2172
+
2173
+
2174
+
2175
+
2176
+
2177
+
2178
+
2179
+ * @example
2180
+ * // Remove all
2181
+ * const list = new DoublyLinkedList<number>([1, 2]);
2182
+ * list.clear();
2183
+ * console.log(list.isEmpty()); // true;
2184
+ */
1790
2185
  clear() {
1791
2186
  this._head = void 0;
1792
2187
  this._tail = void 0;
1793
2188
  this._length = 0;
1794
2189
  }
1795
2190
  /**
1796
- * Find the first value matching a predicate scanning forward.
1797
- * @remarks Time O(N), Space O(1)
1798
- * @param elementNodeOrPredicate - Element, node, or predicate to match.
1799
- * @returns Matched value or undefined.
1800
- */
2191
+ * Find the first value matching a predicate scanning forward.
2192
+ * @remarks Time O(N), Space O(1)
2193
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
2194
+ * @returns Matched value or undefined.
2195
+
2196
+
2197
+
2198
+
2199
+
2200
+
2201
+
2202
+
2203
+ * @example
2204
+ * // Search with predicate
2205
+ * const list = new DoublyLinkedList<number>([10, 20, 30]);
2206
+ * const found = list.search(node => node.value > 15);
2207
+ * console.log(found); // 20;
2208
+ */
1801
2209
  search(elementNodeOrPredicate) {
1802
2210
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
1803
2211
  let current = this.head;
@@ -1808,11 +2216,25 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1808
2216
  return void 0;
1809
2217
  }
1810
2218
  /**
1811
- * Find the first value matching a predicate scanning backward.
1812
- * @remarks Time O(N), Space O(1)
1813
- * @param elementNodeOrPredicate - Element, node, or predicate to match.
1814
- * @returns Matched value or undefined.
1815
- */
2219
+ * Find the first value matching a predicate scanning backward.
2220
+ * @remarks Time O(N), Space O(1)
2221
+ * @param elementNodeOrPredicate - Element, node, or predicate to match.
2222
+ * @returns Matched value or undefined.
2223
+
2224
+
2225
+
2226
+
2227
+
2228
+
2229
+
2230
+
2231
+ * @example
2232
+ * // Find value scanning from tail
2233
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
2234
+ * // getBackward scans from tail to head, returns first match
2235
+ * const found = list.getBackward(node => node.value < 4);
2236
+ * console.log(found); // 3;
2237
+ */
1816
2238
  getBackward(elementNodeOrPredicate) {
1817
2239
  const predicate = this._ensurePredicate(elementNodeOrPredicate);
1818
2240
  let current = this.tail;
@@ -1823,10 +2245,26 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1823
2245
  return void 0;
1824
2246
  }
1825
2247
  /**
1826
- * Reverse the list in place.
1827
- * @remarks Time O(N), Space O(1)
1828
- * @returns This list.
1829
- */
2248
+ * Reverse the list in place.
2249
+ * @remarks Time O(N), Space O(1)
2250
+ * @returns This list.
2251
+
2252
+
2253
+
2254
+
2255
+
2256
+
2257
+
2258
+
2259
+
2260
+
2261
+
2262
+ * @example
2263
+ * // Reverse in-place
2264
+ * const list = new DoublyLinkedList<number>([1, 2, 3]);
2265
+ * list.reverse();
2266
+ * console.log([...list]); // [3, 2, 1];
2267
+ */
1830
2268
  reverse() {
1831
2269
  let current = this.head;
1832
2270
  [this._head, this._tail] = [this.tail, this.head];
@@ -1848,22 +2286,53 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1848
2286
  return this;
1849
2287
  }
1850
2288
  /**
1851
- * Deep clone this list (values are copied by reference).
1852
- * @remarks Time O(N), Space O(N)
1853
- * @returns A new list with the same element sequence.
1854
- */
2289
+ * Deep clone this list (values are copied by reference).
2290
+ * @remarks Time O(N), Space O(N)
2291
+ * @returns A new list with the same element sequence.
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+
2299
+
2300
+
2301
+ * @example
2302
+ * // Deep copy
2303
+ * const list = new DoublyLinkedList<number>([1, 2, 3]);
2304
+ * const copy = list.clone();
2305
+ * copy.pop();
2306
+ * console.log(list.length); // 3;
2307
+ */
1855
2308
  clone() {
1856
2309
  const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1857
2310
  for (const v of this) out.push(v);
1858
2311
  return out;
1859
2312
  }
1860
2313
  /**
1861
- * Filter values into a new list of the same class.
1862
- * @remarks Time O(N), Space O(N)
1863
- * @param callback - Predicate (value, index, list) → boolean to keep value.
1864
- * @param [thisArg] - Value for `this` inside the callback.
1865
- * @returns A new list with kept values.
1866
- */
2314
+ * Filter values into a new list of the same class.
2315
+ * @remarks Time O(N), Space O(N)
2316
+ * @param callback - Predicate (value, index, list) → boolean to keep value.
2317
+ * @param [thisArg] - Value for `this` inside the callback.
2318
+ * @returns A new list with kept values.
2319
+
2320
+
2321
+
2322
+
2323
+
2324
+
2325
+
2326
+
2327
+
2328
+
2329
+
2330
+ * @example
2331
+ * // Filter elements
2332
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
2333
+ * const evens = list.filter(n => n % 2 === 0);
2334
+ * console.log([...evens]); // [2, 4];
2335
+ */
1867
2336
  filter(callback, thisArg) {
1868
2337
  const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
1869
2338
  let index = 0;
@@ -1887,15 +2356,40 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1887
2356
  return out;
1888
2357
  }
1889
2358
  /**
1890
- * Map values into a new list (possibly different element type).
1891
- * @remarks Time O(N), Space O(N)
1892
- * @template EM
1893
- * @template RM
1894
- * @param callback - Mapping function (value, index, list) → newElement.
1895
- * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
1896
- * @param [thisArg] - Value for `this` inside the callback.
1897
- * @returns A new DoublyLinkedList with mapped values.
1898
- */
2359
+ * Map values into a new list (possibly different element type).
2360
+ * @remarks Time O(N), Space O(N)
2361
+ * @template EM
2362
+ * @template RM
2363
+ * @param callback - Mapping function (value, index, list) → newElement.
2364
+ * @param [options] - Options for the output list (e.g., maxLen, toElementFn).
2365
+ * @param [thisArg] - Value for `this` inside the callback.
2366
+ * @returns A new DoublyLinkedList with mapped values.
2367
+
2368
+
2369
+
2370
+
2371
+
2372
+
2373
+
2374
+
2375
+
2376
+
2377
+
2378
+ * @example
2379
+ * // DoublyLinkedList for...of iteration and map operation
2380
+ * const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
2381
+ *
2382
+ * // Iterate through list
2383
+ * const doubled = list.map(value => value * 2);
2384
+ * console.log(doubled.length); // 5;
2385
+ *
2386
+ * // Use for...of loop
2387
+ * const result: number[] = [];
2388
+ * for (const item of list) {
2389
+ * result.push(item);
2390
+ * }
2391
+ * console.log(result); // [1, 2, 3, 4, 5];
2392
+ */
1899
2393
  map(callback, options, thisArg) {
1900
2394
  const out = this._createLike([], { ...options ?? {}, maxLen: this._maxLen });
1901
2395
  let index = 0;
@@ -1984,6 +2478,237 @@ var DoublyLinkedList = class extends LinearLinkedBase {
1984
2478
  }
1985
2479
  };
1986
2480
 
2481
+ // src/common/error.ts
2482
+ var ERR = {
2483
+ // Range / index
2484
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
2485
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
2486
+ // Type / argument
2487
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
2488
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
2489
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
2490
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
2491
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
2492
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
2493
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
2494
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
2495
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
2496
+ // State / operation
2497
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
2498
+ // Matrix
2499
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
2500
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
2501
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
2502
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
2503
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
2504
+ };
2505
+
2506
+ // src/common/index.ts
2507
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
2508
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
2509
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
2510
+ return DFSOperation2;
2511
+ })(DFSOperation || {});
2512
+ var Range = class {
2513
+ constructor(low, high, includeLow = true, includeHigh = true) {
2514
+ this.low = low;
2515
+ this.high = high;
2516
+ this.includeLow = includeLow;
2517
+ this.includeHigh = includeHigh;
2518
+ }
2519
+ static {
2520
+ __name(this, "Range");
2521
+ }
2522
+ // Determine whether a key is within the range
2523
+ isInRange(key, comparator) {
2524
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
2525
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
2526
+ return lowCheck && highCheck;
2527
+ }
2528
+ };
2529
+
2530
+ // src/data-structures/base/iterable-entry-base.ts
2531
+ var IterableEntryBase = class {
2532
+ static {
2533
+ __name(this, "IterableEntryBase");
2534
+ }
2535
+ /**
2536
+ * Default iterator yielding `[key, value]` entries.
2537
+ * @returns Iterator of `[K, V]`.
2538
+ * @remarks Time O(n) to iterate, Space O(1)
2539
+ */
2540
+ *[Symbol.iterator](...args) {
2541
+ yield* this._getIterator(...args);
2542
+ }
2543
+ /**
2544
+ * Iterate over `[key, value]` pairs (may yield `undefined` values).
2545
+ * @returns Iterator of `[K, V | undefined]`.
2546
+ * @remarks Time O(n), Space O(1)
2547
+ */
2548
+ *entries() {
2549
+ for (const item of this) {
2550
+ yield item;
2551
+ }
2552
+ }
2553
+ /**
2554
+ * Iterate over keys only.
2555
+ * @returns Iterator of keys.
2556
+ * @remarks Time O(n), Space O(1)
2557
+ */
2558
+ *keys() {
2559
+ for (const item of this) {
2560
+ yield item[0];
2561
+ }
2562
+ }
2563
+ /**
2564
+ * Iterate over values only.
2565
+ * @returns Iterator of values.
2566
+ * @remarks Time O(n), Space O(1)
2567
+ */
2568
+ *values() {
2569
+ for (const item of this) {
2570
+ yield item[1];
2571
+ }
2572
+ }
2573
+ /**
2574
+ * Test whether all entries satisfy the predicate.
2575
+ * @param predicate - `(key, value, index, self) => boolean`.
2576
+ * @param thisArg - Optional `this` for callback.
2577
+ * @returns `true` if all pass; otherwise `false`.
2578
+ * @remarks Time O(n), Space O(1)
2579
+ */
2580
+ every(predicate, thisArg) {
2581
+ let index = 0;
2582
+ for (const item of this) {
2583
+ if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
2584
+ return false;
2585
+ }
2586
+ }
2587
+ return true;
2588
+ }
2589
+ /**
2590
+ * Test whether any entry satisfies the predicate.
2591
+ * @param predicate - `(key, value, index, self) => boolean`.
2592
+ * @param thisArg - Optional `this` for callback.
2593
+ * @returns `true` if any passes; otherwise `false`.
2594
+ * @remarks Time O(n), Space O(1)
2595
+ */
2596
+ some(predicate, thisArg) {
2597
+ let index = 0;
2598
+ for (const item of this) {
2599
+ if (predicate.call(thisArg, item[1], item[0], index++, this)) {
2600
+ return true;
2601
+ }
2602
+ }
2603
+ return false;
2604
+ }
2605
+ /**
2606
+ * Visit each entry, left-to-right.
2607
+ * @param callbackfn - `(key, value, index, self) => void`.
2608
+ * @param thisArg - Optional `this` for callback.
2609
+ * @remarks Time O(n), Space O(1)
2610
+ */
2611
+ forEach(callbackfn, thisArg) {
2612
+ let index = 0;
2613
+ for (const item of this) {
2614
+ const [key, value] = item;
2615
+ callbackfn.call(thisArg, value, key, index++, this);
2616
+ }
2617
+ }
2618
+ /**
2619
+ * Find the first entry that matches a predicate.
2620
+ * @param callbackfn - `(key, value, index, self) => boolean`.
2621
+ * @param thisArg - Optional `this` for callback.
2622
+ * @returns Matching `[key, value]` or `undefined`.
2623
+ * @remarks Time O(n), Space O(1)
2624
+ */
2625
+ find(callbackfn, thisArg) {
2626
+ let index = 0;
2627
+ for (const item of this) {
2628
+ const [key, value] = item;
2629
+ if (callbackfn.call(thisArg, value, key, index++, this)) return item;
2630
+ }
2631
+ return;
2632
+ }
2633
+ /**
2634
+ * Whether the given key exists.
2635
+ * @param key - Key to test.
2636
+ * @returns `true` if found; otherwise `false`.
2637
+ * @remarks Time O(n) generic, Space O(1)
2638
+ */
2639
+ has(key) {
2640
+ for (const item of this) {
2641
+ const [itemKey] = item;
2642
+ if (itemKey === key) return true;
2643
+ }
2644
+ return false;
2645
+ }
2646
+ /**
2647
+ * Whether there exists an entry with the given value.
2648
+ * @param value - Value to test.
2649
+ * @returns `true` if found; otherwise `false`.
2650
+ * @remarks Time O(n), Space O(1)
2651
+ */
2652
+ hasValue(value) {
2653
+ for (const [, elementValue] of this) {
2654
+ if (elementValue === value) return true;
2655
+ }
2656
+ return false;
2657
+ }
2658
+ /**
2659
+ * Get the value under a key.
2660
+ * @param key - Key to look up.
2661
+ * @returns Value or `undefined`.
2662
+ * @remarks Time O(n) generic, Space O(1)
2663
+ */
2664
+ get(key) {
2665
+ for (const item of this) {
2666
+ const [itemKey, value] = item;
2667
+ if (itemKey === key) return value;
2668
+ }
2669
+ return;
2670
+ }
2671
+ /**
2672
+ * Reduce entries into a single accumulator.
2673
+ * @param callbackfn - `(acc, value, key, index, self) => acc`.
2674
+ * @param initialValue - Initial accumulator.
2675
+ * @returns Final accumulator.
2676
+ * @remarks Time O(n), Space O(1)
2677
+ */
2678
+ reduce(callbackfn, initialValue) {
2679
+ let accumulator = initialValue;
2680
+ let index = 0;
2681
+ for (const item of this) {
2682
+ const [key, value] = item;
2683
+ accumulator = callbackfn(accumulator, value, key, index++, this);
2684
+ }
2685
+ return accumulator;
2686
+ }
2687
+ /**
2688
+ * Converts data structure to `[key, value]` pairs.
2689
+ * @returns Array of entries.
2690
+ * @remarks Time O(n), Space O(n)
2691
+ */
2692
+ toArray() {
2693
+ return [...this];
2694
+ }
2695
+ /**
2696
+ * Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
2697
+ * @returns Array of entries (default) or a string.
2698
+ * @remarks Time O(n), Space O(n)
2699
+ */
2700
+ toVisual() {
2701
+ return [...this];
2702
+ }
2703
+ /**
2704
+ * Print a human-friendly representation to the console.
2705
+ * @remarks Time O(n), Space O(n)
2706
+ */
2707
+ print() {
2708
+ console.log(this.toVisual());
2709
+ }
2710
+ };
2711
+
1987
2712
  // src/data-structures/linked-list/skip-linked-list.ts
1988
2713
  var SkipListNode = class {
1989
2714
  static {
@@ -1995,136 +2720,655 @@ var SkipListNode = class {
1995
2720
  constructor(key, value, level) {
1996
2721
  this.key = key;
1997
2722
  this.value = value;
1998
- this.forward = new Array(level);
2723
+ this.forward = new Array(level).fill(void 0);
1999
2724
  }
2000
2725
  };
2001
- var SkipList = class {
2726
+ var SkipList = class _SkipList extends IterableEntryBase {
2002
2727
  static {
2003
2728
  __name(this, "SkipList");
2004
2729
  }
2005
- constructor(elements = [], options) {
2006
- if (options) {
2007
- const { maxLevel, probability } = options;
2008
- if (typeof maxLevel === "number") this._maxLevel = maxLevel;
2009
- if (typeof probability === "number") this._probability = probability;
2010
- }
2011
- if (elements) {
2012
- for (const [key, value] of elements) this.add(key, value);
2730
+ #comparator;
2731
+ #isDefaultComparator;
2732
+ constructor(entries = [], options = {}) {
2733
+ super();
2734
+ const { comparator, toEntryFn, maxLevel, probability } = options;
2735
+ if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
2736
+ if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
2737
+ this.#isDefaultComparator = comparator === void 0;
2738
+ this.#comparator = comparator ?? _SkipList.createDefaultComparator();
2739
+ this._head = new SkipListNode(void 0, void 0, this._maxLevel);
2740
+ for (const item of entries) {
2741
+ let k;
2742
+ let v;
2743
+ if (toEntryFn) {
2744
+ [k, v] = toEntryFn(item);
2745
+ } else {
2746
+ if (!Array.isArray(item) || item.length < 2) {
2747
+ throw new TypeError(ERR.invalidEntry("SkipList"));
2748
+ }
2749
+ [k, v] = item;
2750
+ }
2751
+ this.set(k, v);
2013
2752
  }
2014
2753
  }
2015
- _head = new SkipListNode(void 0, void 0, this.maxLevel);
2016
- get head() {
2017
- return this._head;
2754
+ /**
2755
+ * Creates a default comparator supporting number, string, Date, and bigint.
2756
+ */
2757
+ static createDefaultComparator() {
2758
+ return (a, b) => {
2759
+ if (typeof a === "number" && typeof b === "number") {
2760
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
2761
+ return a - b;
2762
+ }
2763
+ if (typeof a === "string" && typeof b === "string") {
2764
+ return a < b ? -1 : a > b ? 1 : 0;
2765
+ }
2766
+ if (a instanceof Date && b instanceof Date) {
2767
+ const ta = a.getTime(), tb = b.getTime();
2768
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
2769
+ return ta - tb;
2770
+ }
2771
+ if (typeof a === "bigint" && typeof b === "bigint") {
2772
+ return a < b ? -1 : a > b ? 1 : 0;
2773
+ }
2774
+ throw new TypeError(ERR.comparatorRequired("SkipList"));
2775
+ };
2018
2776
  }
2777
+ // ─── Internal state ──────────────────────────────────────────
2778
+ _head;
2019
2779
  _level = 0;
2020
- get level() {
2021
- return this._level;
2022
- }
2780
+ _size = 0;
2023
2781
  _maxLevel = 16;
2782
+ _probability = 0.5;
2783
+ // ─── Size & lifecycle ────────────────────────────────────────
2784
+ get size() {
2785
+ return this._size;
2786
+ }
2024
2787
  get maxLevel() {
2025
2788
  return this._maxLevel;
2026
2789
  }
2027
- _probability = 0.5;
2028
2790
  get probability() {
2029
2791
  return this._probability;
2030
2792
  }
2031
- get first() {
2032
- const firstNode = this.head.forward[0];
2033
- return firstNode ? firstNode.value : void 0;
2793
+ get comparator() {
2794
+ return this.#comparator;
2795
+ }
2796
+ /**
2797
+ * Check if empty
2798
+
2799
+
2800
+
2801
+
2802
+
2803
+
2804
+
2805
+
2806
+ * @example
2807
+ * // Check if empty
2808
+ * const sl = new SkipList<number, string>();
2809
+ * console.log(sl.isEmpty()); // true;
2810
+ */
2811
+ isEmpty() {
2812
+ return this._size === 0;
2813
+ }
2814
+ /**
2815
+ * Remove all entries
2816
+
2817
+
2818
+
2819
+
2820
+
2821
+
2822
+
2823
+
2824
+ * @example
2825
+ * // Remove all entries
2826
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
2827
+ * sl.clear();
2828
+ * console.log(sl.isEmpty()); // true;
2829
+ */
2830
+ clear() {
2831
+ this._head = new SkipListNode(void 0, void 0, this._maxLevel);
2832
+ this._level = 0;
2833
+ this._size = 0;
2834
+ }
2835
+ /**
2836
+ * Create independent copy
2837
+
2838
+
2839
+
2840
+
2841
+
2842
+
2843
+
2844
+
2845
+ * @example
2846
+ * // Create independent copy
2847
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
2848
+ * const copy = sl.clone();
2849
+ * copy.delete(1);
2850
+ * console.log(sl.has(1)); // true;
2851
+ */
2852
+ clone() {
2853
+ return new _SkipList(this, {
2854
+ comparator: this.#isDefaultComparator ? void 0 : this.#comparator,
2855
+ maxLevel: this._maxLevel,
2856
+ probability: this._probability
2857
+ });
2858
+ }
2859
+ // ─── Core CRUD ───────────────────────────────────────────────
2860
+ /**
2861
+ * Insert or update a key-value pair. Returns `this` for chaining.
2862
+ * Unique keys only — if key exists, value is updated in place.
2863
+
2864
+
2865
+
2866
+
2867
+
2868
+
2869
+
2870
+
2871
+
2872
+
2873
+
2874
+ * @example
2875
+ * // In-memory sorted key-value store
2876
+ * const store = new SkipList<number, string>();
2877
+ *
2878
+ * store.set(3, 'three');
2879
+ * store.set(1, 'one');
2880
+ * store.set(5, 'five');
2881
+ * store.set(2, 'two');
2882
+ *
2883
+ * console.log(store.get(3)); // 'three';
2884
+ * console.log(store.get(1)); // 'one';
2885
+ * console.log(store.get(5)); // 'five';
2886
+ *
2887
+ * // Update existing key
2888
+ * store.set(3, 'THREE');
2889
+ * console.log(store.get(3)); // 'THREE';
2890
+ */
2891
+ set(key, value) {
2892
+ const cmp = this.#comparator;
2893
+ const update = this._findUpdate(key);
2894
+ const existing = update[0].forward[0];
2895
+ if (existing && cmp(existing.key, key) === 0) {
2896
+ existing.value = value;
2897
+ return this;
2898
+ }
2899
+ const newLevel = this._randomLevel();
2900
+ const newNode = new SkipListNode(key, value, newLevel);
2901
+ if (newLevel > this._level) {
2902
+ for (let i = this._level; i < newLevel; i++) {
2903
+ update[i] = this._head;
2904
+ }
2905
+ this._level = newLevel;
2906
+ }
2907
+ for (let i = 0; i < newLevel; i++) {
2908
+ newNode.forward[i] = update[i].forward[i];
2909
+ update[i].forward[i] = newNode;
2910
+ }
2911
+ this._size++;
2912
+ return this;
2034
2913
  }
2035
- get last() {
2036
- let current = this.head;
2037
- for (let i = this.level - 1; i >= 0; i--) {
2914
+ /**
2915
+ * Get the value for a key, or `undefined` if not found.
2916
+ * Overrides base O(n) with O(log n) skip-list search.
2917
+
2918
+
2919
+
2920
+
2921
+
2922
+
2923
+
2924
+
2925
+
2926
+
2927
+
2928
+ * @example
2929
+ * // Building a sorted index
2930
+ * type Product = { id: number; name: string; price: number };
2931
+ * const products: Product[] = [
2932
+ * { id: 1, name: 'Widget', price: 25 },
2933
+ * { id: 2, name: 'Gadget', price: 50 },
2934
+ * { id: 3, name: 'Doohickey', price: 15 }
2935
+ * ];
2936
+ *
2937
+ * const index = new SkipList<number, Product>(products as any, {
2938
+ * toEntryFn: (p: any) => [p.price, p]
2939
+ * });
2940
+ *
2941
+ * // Iterate in sorted order by price
2942
+ * const names = [...index.values()].map(p => p!.name);
2943
+ * console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
2944
+ *
2945
+ * // Range search: products between $20 and $60
2946
+ * const range = index.rangeSearch([20, 60]);
2947
+ * console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
2948
+ */
2949
+ get(key) {
2950
+ const node = this._findNode(key);
2951
+ return node ? node.value : void 0;
2952
+ }
2953
+ /**
2954
+ * Check if a key exists.
2955
+ * Overrides base O(n) with O(log n) skip-list search.
2956
+
2957
+
2958
+
2959
+
2960
+
2961
+
2962
+
2963
+
2964
+
2965
+
2966
+
2967
+ * @example
2968
+ * // Check key existence
2969
+ * const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
2970
+ * console.log(sl.has(3)); // true;
2971
+ * console.log(sl.has(4)); // false;
2972
+ */
2973
+ has(key) {
2974
+ return this._findNode(key) !== void 0;
2975
+ }
2976
+ /**
2977
+ * Delete a key. Returns `true` if the key was found and removed.
2978
+
2979
+
2980
+
2981
+
2982
+
2983
+
2984
+
2985
+
2986
+
2987
+
2988
+
2989
+ * @example
2990
+ * // Fast lookup with deletion
2991
+ * const cache = new SkipList<string, number>();
2992
+ *
2993
+ * cache.set('alpha', 1);
2994
+ * cache.set('beta', 2);
2995
+ * cache.set('gamma', 3);
2996
+ *
2997
+ * console.log(cache.has('beta')); // true;
2998
+ * cache.delete('beta');
2999
+ * console.log(cache.has('beta')); // false;
3000
+ * console.log(cache.size); // 2;
3001
+ */
3002
+ delete(key) {
3003
+ const cmp = this.#comparator;
3004
+ const update = this._findUpdate(key);
3005
+ const target = update[0].forward[0];
3006
+ if (!target || cmp(target.key, key) !== 0) return false;
3007
+ for (let i = 0; i < this._level; i++) {
3008
+ if (update[i].forward[i] !== target) break;
3009
+ update[i].forward[i] = target.forward[i];
3010
+ }
3011
+ while (this._level > 0 && !this._head.forward[this._level - 1]) {
3012
+ this._level--;
3013
+ }
3014
+ this._size--;
3015
+ return true;
3016
+ }
3017
+ // ─── Navigation ──────────────────────────────────────────────
3018
+ /**
3019
+ * Returns the first (smallest key) entry, or `undefined` if empty.
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+
3029
+
3030
+
3031
+ * @example
3032
+ * // Access the minimum entry
3033
+ * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
3034
+ * console.log(sl.first()); // [1, 'a'];
3035
+ */
3036
+ first() {
3037
+ const node = this._head.forward[0];
3038
+ return node ? [node.key, node.value] : void 0;
3039
+ }
3040
+ /**
3041
+ * Returns the last (largest key) entry, or `undefined` if empty.
3042
+
3043
+
3044
+
3045
+
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+
3053
+ * @example
3054
+ * // Access the maximum entry
3055
+ * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
3056
+ * console.log(sl.last()); // [5, 'e'];
3057
+ */
3058
+ last() {
3059
+ let current = this._head;
3060
+ for (let i = this._level - 1; i >= 0; i--) {
2038
3061
  while (current.forward[i]) {
2039
3062
  current = current.forward[i];
2040
3063
  }
2041
3064
  }
2042
- return current.value;
2043
- }
2044
- add(key, value) {
2045
- const newNode = new SkipListNode(key, value, this._randomLevel());
2046
- const update = new Array(this.maxLevel).fill(this.head);
2047
- let current = this.head;
2048
- for (let i = this.level - 1; i >= 0; i--) {
2049
- while (current.forward[i] && current.forward[i].key < key) {
3065
+ return current === this._head ? void 0 : [current.key, current.value];
3066
+ }
3067
+ /**
3068
+ * Remove and return the first (smallest key) entry.
3069
+
3070
+
3071
+
3072
+
3073
+
3074
+
3075
+
3076
+
3077
+ * @example
3078
+ * // Remove and return smallest
3079
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
3080
+ * console.log(sl.pollFirst()); // [1, 'a'];
3081
+ * console.log(sl.size); // 2;
3082
+ */
3083
+ pollFirst() {
3084
+ const entry = this.first();
3085
+ if (!entry) return void 0;
3086
+ this.delete(entry[0]);
3087
+ return entry;
3088
+ }
3089
+ /**
3090
+ * Remove and return the last (largest key) entry.
3091
+
3092
+
3093
+
3094
+
3095
+
3096
+
3097
+
3098
+
3099
+ * @example
3100
+ * // Remove and return largest
3101
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
3102
+ * console.log(sl.pollLast()); // [3, 'c'];
3103
+ * console.log(sl.size); // 2;
3104
+ */
3105
+ pollLast() {
3106
+ const entry = this.last();
3107
+ if (!entry) return void 0;
3108
+ this.delete(entry[0]);
3109
+ return entry;
3110
+ }
3111
+ /**
3112
+ * Least entry ≥ key, or `undefined`.
3113
+
3114
+
3115
+
3116
+
3117
+
3118
+
3119
+
3120
+
3121
+
3122
+
3123
+
3124
+ * @example
3125
+ * // Least entry ≥ key
3126
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
3127
+ * console.log(sl.ceiling(15)); // [20, 'b'];
3128
+ * console.log(sl.ceiling(20)); // [20, 'b'];
3129
+ */
3130
+ ceiling(key) {
3131
+ const cmp = this.#comparator;
3132
+ let current = this._head;
3133
+ for (let i = this._level - 1; i >= 0; i--) {
3134
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
2050
3135
  current = current.forward[i];
2051
3136
  }
2052
- update[i] = current;
2053
3137
  }
2054
- for (let i = 0; i < newNode.forward.length; i++) {
2055
- newNode.forward[i] = update[i].forward[i];
2056
- update[i].forward[i] = newNode;
2057
- }
2058
- if (!newNode.forward[0]) {
2059
- this._level = Math.max(this.level, newNode.forward.length);
3138
+ const node = current.forward[0];
3139
+ return node ? [node.key, node.value] : void 0;
3140
+ }
3141
+ /**
3142
+ * Greatest entry ≤ key, or `undefined`.
3143
+
3144
+
3145
+
3146
+
3147
+
3148
+
3149
+
3150
+
3151
+
3152
+
3153
+
3154
+ * @example
3155
+ * // Greatest entry ≤ key
3156
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
3157
+ * console.log(sl.floor(25)); // [20, 'b'];
3158
+ * console.log(sl.floor(5)); // undefined;
3159
+ */
3160
+ floor(key) {
3161
+ const cmp = this.#comparator;
3162
+ let current = this._head;
3163
+ for (let i = this._level - 1; i >= 0; i--) {
3164
+ while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
3165
+ current = current.forward[i];
3166
+ }
2060
3167
  }
3168
+ const result = current === this._head ? void 0 : current;
3169
+ if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
3170
+ return void 0;
2061
3171
  }
2062
- get(key) {
2063
- let current = this.head;
2064
- for (let i = this.level - 1; i >= 0; i--) {
2065
- while (current.forward[i] && current.forward[i].key < key) {
3172
+ /**
3173
+ * Least entry strictly > key, or `undefined`.
3174
+
3175
+
3176
+
3177
+
3178
+
3179
+
3180
+
3181
+
3182
+ * @example
3183
+ * // Strictly greater entry
3184
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
3185
+ * console.log(sl.higher(15)); // [20, 'b'];
3186
+ * console.log(sl.higher(30)); // undefined;
3187
+ */
3188
+ higher(key) {
3189
+ const cmp = this.#comparator;
3190
+ let current = this._head;
3191
+ for (let i = this._level - 1; i >= 0; i--) {
3192
+ while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
2066
3193
  current = current.forward[i];
2067
3194
  }
2068
3195
  }
2069
- current = current.forward[0];
2070
- if (current && current.key === key) {
2071
- return current.value;
3196
+ const node = current.forward[0];
3197
+ return node ? [node.key, node.value] : void 0;
3198
+ }
3199
+ /**
3200
+ * Greatest entry strictly < key, or `undefined`.
3201
+
3202
+
3203
+
3204
+
3205
+
3206
+
3207
+
3208
+
3209
+ * @example
3210
+ * // Strictly less entry
3211
+ * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
3212
+ * console.log(sl.lower(25)); // [20, 'b'];
3213
+ * console.log(sl.lower(10)); // undefined;
3214
+ */
3215
+ lower(key) {
3216
+ const cmp = this.#comparator;
3217
+ let current = this._head;
3218
+ let result;
3219
+ for (let i = this._level - 1; i >= 0; i--) {
3220
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
3221
+ current = current.forward[i];
3222
+ }
3223
+ if (current !== this._head && cmp(current.key, key) < 0) {
3224
+ result = current;
3225
+ }
2072
3226
  }
2073
- return void 0;
2074
- }
2075
- has(key) {
2076
- return this.get(key) !== void 0;
2077
- }
2078
- delete(key) {
2079
- const update = new Array(this.maxLevel).fill(this.head);
2080
- let current = this.head;
2081
- for (let i = this.level - 1; i >= 0; i--) {
2082
- while (current.forward[i] && current.forward[i].key < key) {
3227
+ return result ? [result.key, result.value] : void 0;
3228
+ }
3229
+ /**
3230
+ * Returns entries within the given key range.
3231
+
3232
+
3233
+
3234
+
3235
+
3236
+
3237
+
3238
+
3239
+
3240
+
3241
+
3242
+ * @example
3243
+ * // Find entries in a range
3244
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
3245
+ * const result = sl.rangeSearch([2, 4]);
3246
+ * console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
3247
+ */
3248
+ rangeSearch(range, options = {}) {
3249
+ const { lowInclusive = true, highInclusive = true } = options;
3250
+ const [low, high] = range;
3251
+ const cmp = this.#comparator;
3252
+ const out = [];
3253
+ let current = this._head;
3254
+ for (let i = this._level - 1; i >= 0; i--) {
3255
+ while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
2083
3256
  current = current.forward[i];
2084
3257
  }
2085
- update[i] = current;
2086
3258
  }
2087
3259
  current = current.forward[0];
2088
- if (current && current.key === key) {
2089
- for (let i = 0; i < this.level; i++) {
2090
- if (update[i].forward[i] !== current) {
2091
- break;
2092
- }
2093
- update[i].forward[i] = current.forward[i];
2094
- }
2095
- while (this.level > 0 && !this.head.forward[this.level - 1]) {
2096
- this._level--;
3260
+ while (current) {
3261
+ const cmpHigh = cmp(current.key, high);
3262
+ if (cmpHigh > 0) break;
3263
+ if (cmpHigh === 0 && !highInclusive) break;
3264
+ const cmpLow = cmp(current.key, low);
3265
+ if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
3266
+ out.push([current.key, current.value]);
2097
3267
  }
2098
- return true;
3268
+ current = current.forward[0];
2099
3269
  }
2100
- return false;
3270
+ return out;
2101
3271
  }
2102
- higher(key) {
2103
- let current = this.head;
2104
- for (let i = this.level - 1; i >= 0; i--) {
2105
- while (current.forward[i] && current.forward[i].key <= key) {
3272
+ // ─── Functional (overrides) ──────────────────────────────────
3273
+ /**
3274
+ * Creates a new SkipList with entries transformed by callback.
3275
+
3276
+
3277
+
3278
+
3279
+
3280
+
3281
+
3282
+
3283
+ * @example
3284
+ * // Transform entries
3285
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
3286
+ * const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
3287
+ * console.log([...mapped.values()]); // ['A', 'B'];
3288
+ */
3289
+ map(callback, options) {
3290
+ const out = new _SkipList([], options ?? {});
3291
+ let i = 0;
3292
+ for (const [k, v] of this) {
3293
+ const [nk, nv] = callback(v, k, i++, this);
3294
+ out.set(nk, nv);
3295
+ }
3296
+ return out;
3297
+ }
3298
+ /**
3299
+ * Creates a new SkipList with entries that pass the predicate.
3300
+
3301
+
3302
+
3303
+
3304
+
3305
+
3306
+
3307
+
3308
+ * @example
3309
+ * // Filter entries
3310
+ * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
3311
+ * const result = sl.filter((v, k) => k > 1);
3312
+ * console.log(result.size); // 2;
3313
+ */
3314
+ filter(callbackfn, thisArg) {
3315
+ const out = new _SkipList([], {
3316
+ comparator: this.#isDefaultComparator ? void 0 : this.#comparator,
3317
+ maxLevel: this._maxLevel,
3318
+ probability: this._probability
3319
+ });
3320
+ let i = 0;
3321
+ for (const [k, v] of this) {
3322
+ const ok = callbackfn.call(thisArg, v, k, i++, this);
3323
+ if (ok) out.set(k, v);
3324
+ }
3325
+ return out;
3326
+ }
3327
+ // ─── Iterator (required by IterableEntryBase) ────────────────
3328
+ _getIterator() {
3329
+ const head = this._head;
3330
+ return (function* () {
3331
+ let node = head.forward[0];
3332
+ while (node) {
3333
+ yield [node.key, node.value];
3334
+ node = node.forward[0];
3335
+ }
3336
+ })();
3337
+ }
3338
+ // ─── Internal helpers ────────────────────────────────────────
3339
+ /**
3340
+ * Finds the update array (predecessors at each level) for a given key.
3341
+ */
3342
+ _findUpdate(key) {
3343
+ const cmp = this.#comparator;
3344
+ const update = new Array(this._maxLevel).fill(this._head);
3345
+ let current = this._head;
3346
+ for (let i = this._level - 1; i >= 0; i--) {
3347
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
2106
3348
  current = current.forward[i];
2107
3349
  }
3350
+ update[i] = current;
2108
3351
  }
2109
- const nextNode = current.forward[0];
2110
- return nextNode ? nextNode.value : void 0;
3352
+ return update;
2111
3353
  }
2112
- lower(key) {
2113
- let current = this.head;
2114
- let lastLess = void 0;
2115
- for (let i = this.level - 1; i >= 0; i--) {
2116
- while (current.forward[i] && current.forward[i].key < key) {
3354
+ /**
3355
+ * Finds the node for a given key, or undefined.
3356
+ */
3357
+ _findNode(key) {
3358
+ const cmp = this.#comparator;
3359
+ let current = this._head;
3360
+ for (let i = this._level - 1; i >= 0; i--) {
3361
+ while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
2117
3362
  current = current.forward[i];
2118
3363
  }
2119
- if (current.key < key) {
2120
- lastLess = current;
2121
- }
2122
3364
  }
2123
- return lastLess ? lastLess.value : void 0;
3365
+ const candidate = current.forward[0];
3366
+ if (candidate && cmp(candidate.key, key) === 0) return candidate;
3367
+ return void 0;
2124
3368
  }
2125
3369
  _randomLevel() {
2126
3370
  let level = 1;
2127
- while (Math.random() < this.probability && level < this.maxLevel) {
3371
+ while (Math.random() < this._probability && level < this._maxLevel) {
2128
3372
  level++;
2129
3373
  }
2130
3374
  return level;