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