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