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