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,57 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __typeError = (msg) => {
|
|
5
|
+
throw TypeError(msg);
|
|
6
|
+
};
|
|
4
7
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
8
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
9
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
12
|
-
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
13
|
-
// Type / argument
|
|
14
|
-
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
15
|
-
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
16
|
-
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
17
|
-
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
18
|
-
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
19
|
-
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
20
|
-
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
21
|
-
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
22
|
-
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
23
|
-
// State / operation
|
|
24
|
-
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
25
|
-
// Matrix
|
|
26
|
-
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
27
|
-
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
28
|
-
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
29
|
-
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
30
|
-
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// src/common/index.ts
|
|
34
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
35
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
36
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
37
|
-
return DFSOperation2;
|
|
38
|
-
})(DFSOperation || {});
|
|
39
|
-
var _Range = class _Range {
|
|
40
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
41
|
-
this.low = low;
|
|
42
|
-
this.high = high;
|
|
43
|
-
this.includeLow = includeLow;
|
|
44
|
-
this.includeHigh = includeHigh;
|
|
45
|
-
}
|
|
46
|
-
// Determine whether a key is within the range
|
|
47
|
-
isInRange(key, comparator) {
|
|
48
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
49
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
50
|
-
return lowCheck && highCheck;
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
__name(_Range, "Range");
|
|
54
|
-
var Range = _Range;
|
|
10
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
11
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
12
|
+
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);
|
|
13
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
55
14
|
|
|
56
15
|
// src/data-structures/base/iterable-element-base.ts
|
|
57
16
|
var _IterableElementBase = class _IterableElementBase {
|
|
@@ -75,7 +34,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
75
34
|
if (options) {
|
|
76
35
|
const { toElementFn } = options;
|
|
77
36
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
78
|
-
else if (toElementFn) throw new TypeError(
|
|
37
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
79
38
|
}
|
|
80
39
|
}
|
|
81
40
|
/**
|
|
@@ -231,7 +190,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
231
190
|
acc = initialValue;
|
|
232
191
|
} else {
|
|
233
192
|
const first = iter.next();
|
|
234
|
-
if (first.done) throw new TypeError(
|
|
193
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
235
194
|
acc = first.value;
|
|
236
195
|
index = 1;
|
|
237
196
|
}
|
|
@@ -769,11 +728,58 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
769
728
|
return list;
|
|
770
729
|
}
|
|
771
730
|
/**
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
731
|
+
* Append an element/node to the tail.
|
|
732
|
+
* @remarks Time O(1), Space O(1)
|
|
733
|
+
* @param elementOrNode - Element or node to append.
|
|
734
|
+
* @returns True when appended.
|
|
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
|
+
|
|
766
|
+
|
|
767
|
+
* @example
|
|
768
|
+
* // basic SinglyLinkedList creation and push operation
|
|
769
|
+
* // Create a simple SinglyLinkedList with initial values
|
|
770
|
+
* const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
|
771
|
+
*
|
|
772
|
+
* // Verify the list maintains insertion order
|
|
773
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
774
|
+
*
|
|
775
|
+
* // Check length
|
|
776
|
+
* console.log(list.length); // 5;
|
|
777
|
+
*
|
|
778
|
+
* // Push a new element to the end
|
|
779
|
+
* list.push(6);
|
|
780
|
+
* console.log(list.length); // 6;
|
|
781
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
782
|
+
*/
|
|
777
783
|
push(elementOrNode) {
|
|
778
784
|
const newNode = this._ensureNode(elementOrNode);
|
|
779
785
|
if (!this.head) {
|
|
@@ -787,10 +793,57 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
787
793
|
return true;
|
|
788
794
|
}
|
|
789
795
|
/**
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
796
|
+
* Remove and return the tail element.
|
|
797
|
+
* @remarks Time O(N), Space O(1)
|
|
798
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
830
|
+
|
|
831
|
+
* @example
|
|
832
|
+
* // SinglyLinkedList pop and shift operations
|
|
833
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
834
|
+
*
|
|
835
|
+
* // Pop removes from the end
|
|
836
|
+
* const last = list.pop();
|
|
837
|
+
* console.log(last); // 50;
|
|
838
|
+
*
|
|
839
|
+
* // Shift removes from the beginning
|
|
840
|
+
* const first = list.shift();
|
|
841
|
+
* console.log(first); // 10;
|
|
842
|
+
*
|
|
843
|
+
* // Verify remaining elements
|
|
844
|
+
* console.log([...list]); // [20, 30, 40];
|
|
845
|
+
* console.log(list.length); // 3;
|
|
846
|
+
*/
|
|
794
847
|
pop() {
|
|
795
848
|
var _a;
|
|
796
849
|
if (!this.head) return void 0;
|
|
@@ -810,10 +863,47 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
810
863
|
return value;
|
|
811
864
|
}
|
|
812
865
|
/**
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
866
|
+
* Remove and return the head element.
|
|
867
|
+
* @remarks Time O(1), Space O(1)
|
|
868
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
900
|
+
|
|
901
|
+
* @example
|
|
902
|
+
* // Remove from the front
|
|
903
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30]);
|
|
904
|
+
* console.log(list.shift()); // 10;
|
|
905
|
+
* console.log(list.length); // 2;
|
|
906
|
+
*/
|
|
817
907
|
shift() {
|
|
818
908
|
if (!this.head) return void 0;
|
|
819
909
|
const removed = this.head;
|
|
@@ -823,11 +913,63 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
823
913
|
return removed.value;
|
|
824
914
|
}
|
|
825
915
|
/**
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
916
|
+
* Prepend an element/node to the head.
|
|
917
|
+
* @remarks Time O(1), Space O(1)
|
|
918
|
+
* @param elementOrNode - Element or node to prepend.
|
|
919
|
+
* @returns True when prepended.
|
|
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
|
+
|
|
951
|
+
|
|
952
|
+
* @example
|
|
953
|
+
* // SinglyLinkedList unshift and forward traversal
|
|
954
|
+
* const list = new SinglyLinkedList<number>([20, 30, 40]);
|
|
955
|
+
*
|
|
956
|
+
* // Unshift adds to the beginning
|
|
957
|
+
* list.unshift(10);
|
|
958
|
+
* console.log([...list]); // [10, 20, 30, 40];
|
|
959
|
+
*
|
|
960
|
+
* // Access elements (forward traversal only for singly linked)
|
|
961
|
+
* const second = list.at(1);
|
|
962
|
+
* console.log(second); // 20;
|
|
963
|
+
*
|
|
964
|
+
* // SinglyLinkedList allows forward iteration only
|
|
965
|
+
* const elements: number[] = [];
|
|
966
|
+
* for (const item of list) {
|
|
967
|
+
* elements.push(item);
|
|
968
|
+
* }
|
|
969
|
+
* console.log(elements); // [10, 20, 30, 40];
|
|
970
|
+
*
|
|
971
|
+
* console.log(list.length); // 4;
|
|
972
|
+
*/
|
|
831
973
|
unshift(elementOrNode) {
|
|
832
974
|
const newNode = this._ensureNode(elementOrNode);
|
|
833
975
|
if (!this.head) {
|
|
@@ -883,11 +1025,49 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
883
1025
|
return void 0;
|
|
884
1026
|
}
|
|
885
1027
|
/**
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1028
|
+
* Get the element at a given index.
|
|
1029
|
+
* @remarks Time O(N), Space O(1)
|
|
1030
|
+
* @param index - Zero-based index.
|
|
1031
|
+
* @returns Element or undefined.
|
|
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
|
+
|
|
1063
|
+
|
|
1064
|
+
* @example
|
|
1065
|
+
* // Access element by index
|
|
1066
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
|
|
1067
|
+
* console.log(list.at(0)); // 'a';
|
|
1068
|
+
* console.log(list.at(2)); // 'c';
|
|
1069
|
+
* console.log(list.at(3)); // 'd';
|
|
1070
|
+
*/
|
|
891
1071
|
at(index) {
|
|
892
1072
|
if (index < 0 || index >= this._length) return void 0;
|
|
893
1073
|
let current = this.head;
|
|
@@ -904,11 +1084,44 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
904
1084
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
905
1085
|
}
|
|
906
1086
|
/**
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1087
|
+
* Get the node reference at a given index.
|
|
1088
|
+
* @remarks Time O(N), Space O(1)
|
|
1089
|
+
* @param index - Zero-based index.
|
|
1090
|
+
* @returns Node or undefined.
|
|
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
|
+
|
|
1119
|
+
|
|
1120
|
+
* @example
|
|
1121
|
+
* // Get node at index
|
|
1122
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1123
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
1124
|
+
*/
|
|
912
1125
|
getNodeAt(index) {
|
|
913
1126
|
if (index < 0 || index >= this._length) return void 0;
|
|
914
1127
|
let current = this.head;
|
|
@@ -916,11 +1129,45 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
916
1129
|
return current;
|
|
917
1130
|
}
|
|
918
1131
|
/**
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1132
|
+
* Delete the element at an index.
|
|
1133
|
+
* @remarks Time O(N), Space O(1)
|
|
1134
|
+
* @param index - Zero-based index.
|
|
1135
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
1164
|
+
|
|
1165
|
+
* @example
|
|
1166
|
+
* // Remove by index
|
|
1167
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1168
|
+
* list.deleteAt(1);
|
|
1169
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
1170
|
+
*/
|
|
924
1171
|
deleteAt(index) {
|
|
925
1172
|
if (index < 0 || index >= this._length) return void 0;
|
|
926
1173
|
if (index === 0) return this.shift();
|
|
@@ -933,11 +1180,45 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
933
1180
|
return value;
|
|
934
1181
|
}
|
|
935
1182
|
/**
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1183
|
+
* Delete the first match by value/node.
|
|
1184
|
+
* @remarks Time O(N), Space O(1)
|
|
1185
|
+
* @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
|
|
1186
|
+
* @returns True if removed.
|
|
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
|
+
|
|
1215
|
+
|
|
1216
|
+
* @example
|
|
1217
|
+
* // Remove first occurrence
|
|
1218
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
|
|
1219
|
+
* list.delete(2);
|
|
1220
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
1221
|
+
*/
|
|
941
1222
|
delete(elementOrNode) {
|
|
942
1223
|
if (elementOrNode === void 0 || !this.head) return false;
|
|
943
1224
|
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
@@ -954,12 +1235,46 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
954
1235
|
return true;
|
|
955
1236
|
}
|
|
956
1237
|
/**
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1238
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
1239
|
+
* @remarks Time O(N), Space O(1)
|
|
1240
|
+
* @param index - Zero-based index.
|
|
1241
|
+
* @param newElementOrNode - Element or node to insert.
|
|
1242
|
+
* @returns True if inserted.
|
|
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
|
+
|
|
1271
|
+
|
|
1272
|
+
* @example
|
|
1273
|
+
* // Insert at index
|
|
1274
|
+
* const list = new SinglyLinkedList<number>([1, 3]);
|
|
1275
|
+
* list.addAt(1, 2);
|
|
1276
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
1277
|
+
*/
|
|
963
1278
|
addAt(index, newElementOrNode) {
|
|
964
1279
|
if (index < 0 || index > this._length) return false;
|
|
965
1280
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -985,28 +1300,133 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
985
1300
|
return true;
|
|
986
1301
|
}
|
|
987
1302
|
/**
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1303
|
+
* Check whether the list is empty.
|
|
1304
|
+
* @remarks Time O(1), Space O(1)
|
|
1305
|
+
* @returns True if length is 0.
|
|
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
|
+
|
|
1335
|
+
|
|
1336
|
+
* @example
|
|
1337
|
+
* // Check empty
|
|
1338
|
+
* console.log(new SinglyLinkedList().isEmpty()); // true;
|
|
1339
|
+
*/
|
|
992
1340
|
isEmpty() {
|
|
993
1341
|
return this._length === 0;
|
|
994
1342
|
}
|
|
995
1343
|
/**
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1344
|
+
* Remove all nodes and reset length.
|
|
1345
|
+
* @remarks Time O(N), Space O(1)
|
|
1346
|
+
* @returns void
|
|
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
|
+
|
|
1376
|
+
|
|
1377
|
+
* @example
|
|
1378
|
+
* // Remove all
|
|
1379
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1380
|
+
* list.clear();
|
|
1381
|
+
* console.log(list.isEmpty()); // true;
|
|
1382
|
+
*/
|
|
1000
1383
|
clear() {
|
|
1001
1384
|
this._head = void 0;
|
|
1002
1385
|
this._tail = void 0;
|
|
1003
1386
|
this._length = 0;
|
|
1004
1387
|
}
|
|
1005
1388
|
/**
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1389
|
+
* Reverse the list in place.
|
|
1390
|
+
* @remarks Time O(N), Space O(1)
|
|
1391
|
+
* @returns This list.
|
|
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
|
+
|
|
1423
|
+
|
|
1424
|
+
* @example
|
|
1425
|
+
* // Reverse the list in-place
|
|
1426
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
|
|
1427
|
+
* list.reverse();
|
|
1428
|
+
* console.log([...list]); // [4, 3, 2, 1];
|
|
1429
|
+
*/
|
|
1010
1430
|
reverse() {
|
|
1011
1431
|
if (!this.head || this.head === this.tail) return this;
|
|
1012
1432
|
let prev;
|
|
@@ -1181,22 +1601,106 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
1181
1601
|
return false;
|
|
1182
1602
|
}
|
|
1183
1603
|
/**
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1604
|
+
* Deep clone this list (values are copied by reference).
|
|
1605
|
+
* @remarks Time O(N), Space O(N)
|
|
1606
|
+
* @returns A new list with the same element sequence.
|
|
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
|
+
|
|
1636
|
+
|
|
1637
|
+
* @example
|
|
1638
|
+
* // Deep copy
|
|
1639
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1640
|
+
* const copy = list.clone();
|
|
1641
|
+
* copy.pop();
|
|
1642
|
+
* console.log(list.length); // 3;
|
|
1643
|
+
* console.log(copy.length); // 2;
|
|
1644
|
+
*/
|
|
1188
1645
|
clone() {
|
|
1189
1646
|
const out = this._createInstance();
|
|
1190
1647
|
for (const v of this) out.push(v);
|
|
1191
1648
|
return out;
|
|
1192
1649
|
}
|
|
1193
1650
|
/**
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1651
|
+
* Filter values into a new list of the same class.
|
|
1652
|
+
* @remarks Time O(N), Space O(N)
|
|
1653
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
1654
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1655
|
+
* @returns A new list with kept values.
|
|
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
|
+
|
|
1687
|
+
|
|
1688
|
+
* @example
|
|
1689
|
+
* // SinglyLinkedList filter and map operations
|
|
1690
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
1691
|
+
*
|
|
1692
|
+
* // Filter even numbers
|
|
1693
|
+
* const filtered = list.filter(value => value % 2 === 0);
|
|
1694
|
+
* console.log(filtered.length); // 2;
|
|
1695
|
+
*
|
|
1696
|
+
* // Map to double values
|
|
1697
|
+
* const doubled = list.map(value => value * 2);
|
|
1698
|
+
* console.log(doubled.length); // 5;
|
|
1699
|
+
*
|
|
1700
|
+
* // Use reduce to sum
|
|
1701
|
+
* const sum = list.reduce((acc, value) => acc + value, 0);
|
|
1702
|
+
* console.log(sum); // 15;
|
|
1703
|
+
*/
|
|
1200
1704
|
filter(callback, thisArg) {
|
|
1201
1705
|
const out = this._createInstance();
|
|
1202
1706
|
let index = 0;
|
|
@@ -1220,15 +1724,52 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
1220
1724
|
return out;
|
|
1221
1725
|
}
|
|
1222
1726
|
/**
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1727
|
+
* Map values into a new list (possibly different element type).
|
|
1728
|
+
* @remarks Time O(N), Space O(N)
|
|
1729
|
+
* @template EM
|
|
1730
|
+
* @template RM
|
|
1731
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1732
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1733
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1734
|
+
* @returns A new SinglyLinkedList with mapped values.
|
|
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
|
+
|
|
1766
|
+
|
|
1767
|
+
* @example
|
|
1768
|
+
* // Transform elements
|
|
1769
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1770
|
+
* const doubled = list.map(n => n * 2);
|
|
1771
|
+
* console.log([...doubled]); // [2, 4, 6];
|
|
1772
|
+
*/
|
|
1232
1773
|
map(callback, options, thisArg) {
|
|
1233
1774
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1234
1775
|
let index = 0;
|
|
@@ -1504,11 +2045,58 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1504
2045
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
1505
2046
|
}
|
|
1506
2047
|
/**
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
2048
|
+
* Append an element/node to the tail.
|
|
2049
|
+
* @remarks Time O(1), Space O(1)
|
|
2050
|
+
* @param elementOrNode - Element or node to append.
|
|
2051
|
+
* @returns True when appended.
|
|
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
|
+
|
|
2083
|
+
|
|
2084
|
+
* @example
|
|
2085
|
+
* // basic DoublyLinkedList creation and push operation
|
|
2086
|
+
* // Create a simple DoublyLinkedList with initial values
|
|
2087
|
+
* const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
|
2088
|
+
*
|
|
2089
|
+
* // Verify the list maintains insertion order
|
|
2090
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
2091
|
+
*
|
|
2092
|
+
* // Check length
|
|
2093
|
+
* console.log(list.length); // 5;
|
|
2094
|
+
*
|
|
2095
|
+
* // Push a new element to the end
|
|
2096
|
+
* list.push(6);
|
|
2097
|
+
* console.log(list.length); // 6;
|
|
2098
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
2099
|
+
*/
|
|
1512
2100
|
push(elementOrNode) {
|
|
1513
2101
|
const newNode = this._ensureNode(elementOrNode);
|
|
1514
2102
|
if (!this.head) {
|
|
@@ -1524,10 +2112,57 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1524
2112
|
return true;
|
|
1525
2113
|
}
|
|
1526
2114
|
/**
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
2115
|
+
* Remove and return the tail element.
|
|
2116
|
+
* @remarks Time O(1), Space O(1)
|
|
2117
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
2149
|
+
|
|
2150
|
+
* @example
|
|
2151
|
+
* // DoublyLinkedList pop and shift operations
|
|
2152
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
2153
|
+
*
|
|
2154
|
+
* // Pop removes from the end
|
|
2155
|
+
* const last = list.pop();
|
|
2156
|
+
* console.log(last); // 50;
|
|
2157
|
+
*
|
|
2158
|
+
* // Shift removes from the beginning
|
|
2159
|
+
* const first = list.shift();
|
|
2160
|
+
* console.log(first); // 10;
|
|
2161
|
+
*
|
|
2162
|
+
* // Verify remaining elements
|
|
2163
|
+
* console.log([...list]); // [20, 30, 40];
|
|
2164
|
+
* console.log(list.length); // 3;
|
|
2165
|
+
*/
|
|
1531
2166
|
pop() {
|
|
1532
2167
|
if (!this.tail) return void 0;
|
|
1533
2168
|
const removed = this.tail;
|
|
@@ -1542,10 +2177,47 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1542
2177
|
return removed.value;
|
|
1543
2178
|
}
|
|
1544
2179
|
/**
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
2180
|
+
* Remove and return the head element.
|
|
2181
|
+
* @remarks Time O(1), Space O(1)
|
|
2182
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
2214
|
+
|
|
2215
|
+
* @example
|
|
2216
|
+
* // Remove from the front
|
|
2217
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2218
|
+
* console.log(list.shift()); // 10;
|
|
2219
|
+
* console.log(list.first); // 20;
|
|
2220
|
+
*/
|
|
1549
2221
|
shift() {
|
|
1550
2222
|
if (!this.head) return void 0;
|
|
1551
2223
|
const removed = this.head;
|
|
@@ -1560,11 +2232,48 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1560
2232
|
return removed.value;
|
|
1561
2233
|
}
|
|
1562
2234
|
/**
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
2235
|
+
* Prepend an element/node to the head.
|
|
2236
|
+
* @remarks Time O(1), Space O(1)
|
|
2237
|
+
* @param elementOrNode - Element or node to prepend.
|
|
2238
|
+
* @returns True when prepended.
|
|
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
|
+
|
|
2270
|
+
|
|
2271
|
+
* @example
|
|
2272
|
+
* // Add to the front
|
|
2273
|
+
* const list = new DoublyLinkedList<number>([2, 3]);
|
|
2274
|
+
* list.unshift(1);
|
|
2275
|
+
* console.log([...list]); // [1, 2, 3];
|
|
2276
|
+
*/
|
|
1568
2277
|
unshift(elementOrNode) {
|
|
1569
2278
|
const newNode = this._ensureNode(elementOrNode);
|
|
1570
2279
|
if (!this.head) {
|
|
@@ -1608,11 +2317,48 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1608
2317
|
return ans;
|
|
1609
2318
|
}
|
|
1610
2319
|
/**
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
2320
|
+
* Get the element at a given index.
|
|
2321
|
+
* @remarks Time O(N), Space O(1)
|
|
2322
|
+
* @param index - Zero-based index.
|
|
2323
|
+
* @returns Element or undefined.
|
|
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
|
+
|
|
2355
|
+
|
|
2356
|
+
* @example
|
|
2357
|
+
* // Access by index
|
|
2358
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2359
|
+
* console.log(list.at(1)); // 'b';
|
|
2360
|
+
* console.log(list.at(2)); // 'c';
|
|
2361
|
+
*/
|
|
1616
2362
|
at(index) {
|
|
1617
2363
|
if (index < 0 || index >= this._length) return void 0;
|
|
1618
2364
|
let current = this.head;
|
|
@@ -1620,11 +2366,44 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1620
2366
|
return current == null ? void 0 : current.value;
|
|
1621
2367
|
}
|
|
1622
2368
|
/**
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
2369
|
+
* Get the node reference at a given index.
|
|
2370
|
+
* @remarks Time O(N), Space O(1)
|
|
2371
|
+
* @param index - Zero-based index.
|
|
2372
|
+
* @returns Node or undefined.
|
|
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
|
+
|
|
2401
|
+
|
|
2402
|
+
* @example
|
|
2403
|
+
* // Get node at index
|
|
2404
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2405
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
2406
|
+
*/
|
|
1628
2407
|
getNodeAt(index) {
|
|
1629
2408
|
if (index < 0 || index >= this._length) return void 0;
|
|
1630
2409
|
let current = this.head;
|
|
@@ -1663,12 +2442,46 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1663
2442
|
return void 0;
|
|
1664
2443
|
}
|
|
1665
2444
|
/**
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
2445
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
2446
|
+
* @remarks Time O(N), Space O(1)
|
|
2447
|
+
* @param index - Zero-based index.
|
|
2448
|
+
* @param newElementOrNode - Element or node to insert.
|
|
2449
|
+
* @returns True if inserted.
|
|
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
|
+
|
|
2478
|
+
|
|
2479
|
+
* @example
|
|
2480
|
+
* // Insert at position
|
|
2481
|
+
* const list = new DoublyLinkedList<number>([1, 3]);
|
|
2482
|
+
* list.addAt(1, 2);
|
|
2483
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
2484
|
+
*/
|
|
1672
2485
|
addAt(index, newElementOrNode) {
|
|
1673
2486
|
if (index < 0 || index > this._length) return false;
|
|
1674
2487
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1735,11 +2548,45 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1735
2548
|
return true;
|
|
1736
2549
|
}
|
|
1737
2550
|
/**
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
2551
|
+
* Delete the element at an index.
|
|
2552
|
+
* @remarks Time O(N), Space O(1)
|
|
2553
|
+
* @param index - Zero-based index.
|
|
2554
|
+
* @returns Removed element or undefined.
|
|
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
|
+
|
|
2583
|
+
|
|
2584
|
+
* @example
|
|
2585
|
+
* // Remove by index
|
|
2586
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2587
|
+
* list.deleteAt(1);
|
|
2588
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
2589
|
+
*/
|
|
1743
2590
|
deleteAt(index) {
|
|
1744
2591
|
if (index < 0 || index >= this._length) return;
|
|
1745
2592
|
if (index === 0) return this.shift();
|
|
@@ -1753,11 +2600,45 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1753
2600
|
return removedNode.value;
|
|
1754
2601
|
}
|
|
1755
2602
|
/**
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
2603
|
+
* Delete the first match by value/node.
|
|
2604
|
+
* @remarks Time O(N), Space O(1)
|
|
2605
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
2606
|
+
* @returns True if removed.
|
|
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
|
+
|
|
2635
|
+
|
|
2636
|
+
* @example
|
|
2637
|
+
* // Remove first occurrence
|
|
2638
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
|
|
2639
|
+
* list.delete(2);
|
|
2640
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
2641
|
+
*/
|
|
1761
2642
|
delete(elementOrNode) {
|
|
1762
2643
|
const node = this.getNode(elementOrNode);
|
|
1763
2644
|
if (!node) return false;
|
|
@@ -1773,29 +2654,131 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1773
2654
|
return true;
|
|
1774
2655
|
}
|
|
1775
2656
|
/**
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
2657
|
+
* Check whether the list is empty.
|
|
2658
|
+
* @remarks Time O(1), Space O(1)
|
|
2659
|
+
* @returns True if length is 0.
|
|
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
|
+
|
|
2689
|
+
|
|
2690
|
+
* @example
|
|
2691
|
+
* // Check empty
|
|
2692
|
+
* console.log(new DoublyLinkedList().isEmpty()); // true;
|
|
2693
|
+
*/
|
|
1780
2694
|
isEmpty() {
|
|
1781
2695
|
return this._length === 0;
|
|
1782
2696
|
}
|
|
1783
2697
|
/**
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
2698
|
+
* Remove all nodes and reset length.
|
|
2699
|
+
* @remarks Time O(N), Space O(1)
|
|
2700
|
+
* @returns void
|
|
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
|
+
|
|
2730
|
+
|
|
2731
|
+
* @example
|
|
2732
|
+
* // Remove all
|
|
2733
|
+
* const list = new DoublyLinkedList<number>([1, 2]);
|
|
2734
|
+
* list.clear();
|
|
2735
|
+
* console.log(list.isEmpty()); // true;
|
|
2736
|
+
*/
|
|
1788
2737
|
clear() {
|
|
1789
2738
|
this._head = void 0;
|
|
1790
2739
|
this._tail = void 0;
|
|
1791
2740
|
this._length = 0;
|
|
1792
2741
|
}
|
|
1793
2742
|
/**
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
2743
|
+
* Find the first value matching a predicate scanning forward.
|
|
2744
|
+
* @remarks Time O(N), Space O(1)
|
|
2745
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2746
|
+
* @returns Matched value or undefined.
|
|
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
|
+
|
|
2775
|
+
|
|
2776
|
+
* @example
|
|
2777
|
+
* // Search with predicate
|
|
2778
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2779
|
+
* const found = list.search(node => node.value > 15);
|
|
2780
|
+
* console.log(found); // 20;
|
|
2781
|
+
*/
|
|
1799
2782
|
search(elementNodeOrPredicate) {
|
|
1800
2783
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1801
2784
|
let current = this.head;
|
|
@@ -1806,11 +2789,46 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1806
2789
|
return void 0;
|
|
1807
2790
|
}
|
|
1808
2791
|
/**
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2792
|
+
* Find the first value matching a predicate scanning backward.
|
|
2793
|
+
* @remarks Time O(N), Space O(1)
|
|
2794
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2795
|
+
* @returns Matched value or undefined.
|
|
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
|
+
|
|
2824
|
+
|
|
2825
|
+
* @example
|
|
2826
|
+
* // Find value scanning from tail
|
|
2827
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
|
|
2828
|
+
* // getBackward scans from tail to head, returns first match
|
|
2829
|
+
* const found = list.getBackward(node => node.value < 4);
|
|
2830
|
+
* console.log(found); // 3;
|
|
2831
|
+
*/
|
|
1814
2832
|
getBackward(elementNodeOrPredicate) {
|
|
1815
2833
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1816
2834
|
let current = this.tail;
|
|
@@ -1821,10 +2839,47 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1821
2839
|
return void 0;
|
|
1822
2840
|
}
|
|
1823
2841
|
/**
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
2842
|
+
* Reverse the list in place.
|
|
2843
|
+
* @remarks Time O(N), Space O(1)
|
|
2844
|
+
* @returns This list.
|
|
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
|
+
|
|
2876
|
+
|
|
2877
|
+
* @example
|
|
2878
|
+
* // Reverse in-place
|
|
2879
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2880
|
+
* list.reverse();
|
|
2881
|
+
* console.log([...list]); // [3, 2, 1];
|
|
2882
|
+
*/
|
|
1828
2883
|
reverse() {
|
|
1829
2884
|
let current = this.head;
|
|
1830
2885
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1846,22 +2901,95 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1846
2901
|
return this;
|
|
1847
2902
|
}
|
|
1848
2903
|
/**
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2904
|
+
* Deep clone this list (values are copied by reference).
|
|
2905
|
+
* @remarks Time O(N), Space O(N)
|
|
2906
|
+
* @returns A new list with the same element sequence.
|
|
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
|
+
|
|
2936
|
+
|
|
2937
|
+
* @example
|
|
2938
|
+
* // Deep copy
|
|
2939
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2940
|
+
* const copy = list.clone();
|
|
2941
|
+
* copy.pop();
|
|
2942
|
+
* console.log(list.length); // 3;
|
|
2943
|
+
*/
|
|
1853
2944
|
clone() {
|
|
1854
2945
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1855
2946
|
for (const v of this) out.push(v);
|
|
1856
2947
|
return out;
|
|
1857
2948
|
}
|
|
1858
2949
|
/**
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2950
|
+
* Filter values into a new list of the same class.
|
|
2951
|
+
* @remarks Time O(N), Space O(N)
|
|
2952
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
2953
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2954
|
+
* @returns A new list with kept values.
|
|
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
|
+
|
|
2986
|
+
|
|
2987
|
+
* @example
|
|
2988
|
+
* // Filter elements
|
|
2989
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
2990
|
+
* const evens = list.filter(n => n % 2 === 0);
|
|
2991
|
+
* console.log([...evens]); // [2, 4];
|
|
2992
|
+
*/
|
|
1865
2993
|
filter(callback, thisArg) {
|
|
1866
2994
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1867
2995
|
let index = 0;
|
|
@@ -1885,15 +3013,61 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1885
3013
|
return out;
|
|
1886
3014
|
}
|
|
1887
3015
|
/**
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
3016
|
+
* Map values into a new list (possibly different element type).
|
|
3017
|
+
* @remarks Time O(N), Space O(N)
|
|
3018
|
+
* @template EM
|
|
3019
|
+
* @template RM
|
|
3020
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
3021
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
3022
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
3023
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
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
|
+
|
|
3055
|
+
|
|
3056
|
+
* @example
|
|
3057
|
+
* // DoublyLinkedList for...of iteration and map operation
|
|
3058
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
3059
|
+
*
|
|
3060
|
+
* // Iterate through list
|
|
3061
|
+
* const doubled = list.map(value => value * 2);
|
|
3062
|
+
* console.log(doubled.length); // 5;
|
|
3063
|
+
*
|
|
3064
|
+
* // Use for...of loop
|
|
3065
|
+
* const result: number[] = [];
|
|
3066
|
+
* for (const item of list) {
|
|
3067
|
+
* result.push(item);
|
|
3068
|
+
* }
|
|
3069
|
+
* console.log(result); // [1, 2, 3, 4, 5];
|
|
3070
|
+
*/
|
|
1897
3071
|
map(callback, options, thisArg) {
|
|
1898
3072
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1899
3073
|
let index = 0;
|
|
@@ -1984,6 +3158,235 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1984
3158
|
__name(_DoublyLinkedList, "DoublyLinkedList");
|
|
1985
3159
|
var DoublyLinkedList = _DoublyLinkedList;
|
|
1986
3160
|
|
|
3161
|
+
// src/common/error.ts
|
|
3162
|
+
var ERR = {
|
|
3163
|
+
// Range / index
|
|
3164
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
3165
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
3166
|
+
// Type / argument
|
|
3167
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
3168
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
3169
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
3170
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
3171
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
3172
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
3173
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
3174
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
3175
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
3176
|
+
// State / operation
|
|
3177
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
3178
|
+
// Matrix
|
|
3179
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
3180
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
3181
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
3182
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
3183
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
3184
|
+
};
|
|
3185
|
+
|
|
3186
|
+
// src/common/index.ts
|
|
3187
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
3188
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
3189
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
3190
|
+
return DFSOperation2;
|
|
3191
|
+
})(DFSOperation || {});
|
|
3192
|
+
var _Range = class _Range {
|
|
3193
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
3194
|
+
this.low = low;
|
|
3195
|
+
this.high = high;
|
|
3196
|
+
this.includeLow = includeLow;
|
|
3197
|
+
this.includeHigh = includeHigh;
|
|
3198
|
+
}
|
|
3199
|
+
// Determine whether a key is within the range
|
|
3200
|
+
isInRange(key, comparator) {
|
|
3201
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
3202
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
3203
|
+
return lowCheck && highCheck;
|
|
3204
|
+
}
|
|
3205
|
+
};
|
|
3206
|
+
__name(_Range, "Range");
|
|
3207
|
+
var Range = _Range;
|
|
3208
|
+
|
|
3209
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
3210
|
+
var _IterableEntryBase = class _IterableEntryBase {
|
|
3211
|
+
/**
|
|
3212
|
+
* Default iterator yielding `[key, value]` entries.
|
|
3213
|
+
* @returns Iterator of `[K, V]`.
|
|
3214
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
3215
|
+
*/
|
|
3216
|
+
*[Symbol.iterator](...args) {
|
|
3217
|
+
yield* this._getIterator(...args);
|
|
3218
|
+
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
3221
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
3222
|
+
* @remarks Time O(n), Space O(1)
|
|
3223
|
+
*/
|
|
3224
|
+
*entries() {
|
|
3225
|
+
for (const item of this) {
|
|
3226
|
+
yield item;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
/**
|
|
3230
|
+
* Iterate over keys only.
|
|
3231
|
+
* @returns Iterator of keys.
|
|
3232
|
+
* @remarks Time O(n), Space O(1)
|
|
3233
|
+
*/
|
|
3234
|
+
*keys() {
|
|
3235
|
+
for (const item of this) {
|
|
3236
|
+
yield item[0];
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
/**
|
|
3240
|
+
* Iterate over values only.
|
|
3241
|
+
* @returns Iterator of values.
|
|
3242
|
+
* @remarks Time O(n), Space O(1)
|
|
3243
|
+
*/
|
|
3244
|
+
*values() {
|
|
3245
|
+
for (const item of this) {
|
|
3246
|
+
yield item[1];
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
/**
|
|
3250
|
+
* Test whether all entries satisfy the predicate.
|
|
3251
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
3252
|
+
* @param thisArg - Optional `this` for callback.
|
|
3253
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
3254
|
+
* @remarks Time O(n), Space O(1)
|
|
3255
|
+
*/
|
|
3256
|
+
every(predicate, thisArg) {
|
|
3257
|
+
let index = 0;
|
|
3258
|
+
for (const item of this) {
|
|
3259
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
3260
|
+
return false;
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
return true;
|
|
3264
|
+
}
|
|
3265
|
+
/**
|
|
3266
|
+
* Test whether any entry satisfies the predicate.
|
|
3267
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
3268
|
+
* @param thisArg - Optional `this` for callback.
|
|
3269
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
3270
|
+
* @remarks Time O(n), Space O(1)
|
|
3271
|
+
*/
|
|
3272
|
+
some(predicate, thisArg) {
|
|
3273
|
+
let index = 0;
|
|
3274
|
+
for (const item of this) {
|
|
3275
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
3276
|
+
return true;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
return false;
|
|
3280
|
+
}
|
|
3281
|
+
/**
|
|
3282
|
+
* Visit each entry, left-to-right.
|
|
3283
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
3284
|
+
* @param thisArg - Optional `this` for callback.
|
|
3285
|
+
* @remarks Time O(n), Space O(1)
|
|
3286
|
+
*/
|
|
3287
|
+
forEach(callbackfn, thisArg) {
|
|
3288
|
+
let index = 0;
|
|
3289
|
+
for (const item of this) {
|
|
3290
|
+
const [key, value] = item;
|
|
3291
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
/**
|
|
3295
|
+
* Find the first entry that matches a predicate.
|
|
3296
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
3297
|
+
* @param thisArg - Optional `this` for callback.
|
|
3298
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
3299
|
+
* @remarks Time O(n), Space O(1)
|
|
3300
|
+
*/
|
|
3301
|
+
find(callbackfn, thisArg) {
|
|
3302
|
+
let index = 0;
|
|
3303
|
+
for (const item of this) {
|
|
3304
|
+
const [key, value] = item;
|
|
3305
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
3306
|
+
}
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Whether the given key exists.
|
|
3311
|
+
* @param key - Key to test.
|
|
3312
|
+
* @returns `true` if found; otherwise `false`.
|
|
3313
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
3314
|
+
*/
|
|
3315
|
+
has(key) {
|
|
3316
|
+
for (const item of this) {
|
|
3317
|
+
const [itemKey] = item;
|
|
3318
|
+
if (itemKey === key) return true;
|
|
3319
|
+
}
|
|
3320
|
+
return false;
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Whether there exists an entry with the given value.
|
|
3324
|
+
* @param value - Value to test.
|
|
3325
|
+
* @returns `true` if found; otherwise `false`.
|
|
3326
|
+
* @remarks Time O(n), Space O(1)
|
|
3327
|
+
*/
|
|
3328
|
+
hasValue(value) {
|
|
3329
|
+
for (const [, elementValue] of this) {
|
|
3330
|
+
if (elementValue === value) return true;
|
|
3331
|
+
}
|
|
3332
|
+
return false;
|
|
3333
|
+
}
|
|
3334
|
+
/**
|
|
3335
|
+
* Get the value under a key.
|
|
3336
|
+
* @param key - Key to look up.
|
|
3337
|
+
* @returns Value or `undefined`.
|
|
3338
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
3339
|
+
*/
|
|
3340
|
+
get(key) {
|
|
3341
|
+
for (const item of this) {
|
|
3342
|
+
const [itemKey, value] = item;
|
|
3343
|
+
if (itemKey === key) return value;
|
|
3344
|
+
}
|
|
3345
|
+
return;
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* Reduce entries into a single accumulator.
|
|
3349
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
3350
|
+
* @param initialValue - Initial accumulator.
|
|
3351
|
+
* @returns Final accumulator.
|
|
3352
|
+
* @remarks Time O(n), Space O(1)
|
|
3353
|
+
*/
|
|
3354
|
+
reduce(callbackfn, initialValue) {
|
|
3355
|
+
let accumulator = initialValue;
|
|
3356
|
+
let index = 0;
|
|
3357
|
+
for (const item of this) {
|
|
3358
|
+
const [key, value] = item;
|
|
3359
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
3360
|
+
}
|
|
3361
|
+
return accumulator;
|
|
3362
|
+
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Converts data structure to `[key, value]` pairs.
|
|
3365
|
+
* @returns Array of entries.
|
|
3366
|
+
* @remarks Time O(n), Space O(n)
|
|
3367
|
+
*/
|
|
3368
|
+
toArray() {
|
|
3369
|
+
return [...this];
|
|
3370
|
+
}
|
|
3371
|
+
/**
|
|
3372
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
3373
|
+
* @returns Array of entries (default) or a string.
|
|
3374
|
+
* @remarks Time O(n), Space O(n)
|
|
3375
|
+
*/
|
|
3376
|
+
toVisual() {
|
|
3377
|
+
return [...this];
|
|
3378
|
+
}
|
|
3379
|
+
/**
|
|
3380
|
+
* Print a human-friendly representation to the console.
|
|
3381
|
+
* @remarks Time O(n), Space O(n)
|
|
3382
|
+
*/
|
|
3383
|
+
print() {
|
|
3384
|
+
console.log(this.toVisual());
|
|
3385
|
+
}
|
|
3386
|
+
};
|
|
3387
|
+
__name(_IterableEntryBase, "IterableEntryBase");
|
|
3388
|
+
var IterableEntryBase = _IterableEntryBase;
|
|
3389
|
+
|
|
1987
3390
|
// src/data-structures/linked-list/skip-linked-list.ts
|
|
1988
3391
|
var _SkipListNode = class _SkipListNode {
|
|
1989
3392
|
constructor(key, value, level) {
|
|
@@ -1992,31 +3395,69 @@ var _SkipListNode = class _SkipListNode {
|
|
|
1992
3395
|
__publicField(this, "forward");
|
|
1993
3396
|
this.key = key;
|
|
1994
3397
|
this.value = value;
|
|
1995
|
-
this.forward = new Array(level);
|
|
3398
|
+
this.forward = new Array(level).fill(void 0);
|
|
1996
3399
|
}
|
|
1997
3400
|
};
|
|
1998
3401
|
__name(_SkipListNode, "SkipListNode");
|
|
1999
3402
|
var SkipListNode = _SkipListNode;
|
|
2000
|
-
var
|
|
2001
|
-
|
|
2002
|
-
|
|
3403
|
+
var _comparator, _isDefaultComparator;
|
|
3404
|
+
var _SkipList = class _SkipList extends IterableEntryBase {
|
|
3405
|
+
constructor(entries = [], options = {}) {
|
|
3406
|
+
super();
|
|
3407
|
+
__privateAdd(this, _comparator);
|
|
3408
|
+
__privateAdd(this, _isDefaultComparator);
|
|
3409
|
+
// ─── Internal state ──────────────────────────────────────────
|
|
3410
|
+
__publicField(this, "_head");
|
|
2003
3411
|
__publicField(this, "_level", 0);
|
|
3412
|
+
__publicField(this, "_size", 0);
|
|
2004
3413
|
__publicField(this, "_maxLevel", 16);
|
|
2005
3414
|
__publicField(this, "_probability", 0.5);
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
3415
|
+
const { comparator, toEntryFn, maxLevel, probability } = options;
|
|
3416
|
+
if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
|
|
3417
|
+
if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
|
|
3418
|
+
__privateSet(this, _isDefaultComparator, comparator === void 0);
|
|
3419
|
+
__privateSet(this, _comparator, comparator != null ? comparator : _SkipList.createDefaultComparator());
|
|
3420
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
3421
|
+
for (const item of entries) {
|
|
3422
|
+
let k;
|
|
3423
|
+
let v;
|
|
3424
|
+
if (toEntryFn) {
|
|
3425
|
+
[k, v] = toEntryFn(item);
|
|
3426
|
+
} else {
|
|
3427
|
+
if (!Array.isArray(item) || item.length < 2) {
|
|
3428
|
+
throw new TypeError(ERR.invalidEntry("SkipList"));
|
|
3429
|
+
}
|
|
3430
|
+
[k, v] = item;
|
|
3431
|
+
}
|
|
3432
|
+
this.set(k, v);
|
|
2013
3433
|
}
|
|
2014
3434
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
3435
|
+
/**
|
|
3436
|
+
* Creates a default comparator supporting number, string, Date, and bigint.
|
|
3437
|
+
*/
|
|
3438
|
+
static createDefaultComparator() {
|
|
3439
|
+
return (a, b) => {
|
|
3440
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
3441
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
|
|
3442
|
+
return a - b;
|
|
3443
|
+
}
|
|
3444
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
3445
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3446
|
+
}
|
|
3447
|
+
if (a instanceof Date && b instanceof Date) {
|
|
3448
|
+
const ta = a.getTime(), tb = b.getTime();
|
|
3449
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
|
|
3450
|
+
return ta - tb;
|
|
3451
|
+
}
|
|
3452
|
+
if (typeof a === "bigint" && typeof b === "bigint") {
|
|
3453
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3454
|
+
}
|
|
3455
|
+
throw new TypeError(ERR.comparatorRequired("SkipList"));
|
|
3456
|
+
};
|
|
2017
3457
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
3458
|
+
// ─── Size & lifecycle ────────────────────────────────────────
|
|
3459
|
+
get size() {
|
|
3460
|
+
return this._size;
|
|
2020
3461
|
}
|
|
2021
3462
|
get maxLevel() {
|
|
2022
3463
|
return this._maxLevel;
|
|
@@ -2024,108 +3465,970 @@ var _SkipList = class _SkipList {
|
|
|
2024
3465
|
get probability() {
|
|
2025
3466
|
return this._probability;
|
|
2026
3467
|
}
|
|
2027
|
-
get
|
|
2028
|
-
|
|
2029
|
-
return firstNode ? firstNode.value : void 0;
|
|
3468
|
+
get comparator() {
|
|
3469
|
+
return __privateGet(this, _comparator);
|
|
2030
3470
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
3471
|
+
/**
|
|
3472
|
+
* Check if empty
|
|
3473
|
+
|
|
3474
|
+
|
|
3475
|
+
|
|
3476
|
+
|
|
3477
|
+
|
|
3478
|
+
|
|
3479
|
+
|
|
3480
|
+
|
|
3481
|
+
|
|
3482
|
+
|
|
3483
|
+
|
|
3484
|
+
|
|
3485
|
+
|
|
3486
|
+
|
|
3487
|
+
|
|
3488
|
+
|
|
3489
|
+
|
|
3490
|
+
|
|
3491
|
+
|
|
3492
|
+
|
|
3493
|
+
|
|
3494
|
+
|
|
3495
|
+
|
|
3496
|
+
|
|
3497
|
+
|
|
3498
|
+
|
|
3499
|
+
|
|
3500
|
+
|
|
3501
|
+
|
|
3502
|
+
* @example
|
|
3503
|
+
* // Check if empty
|
|
3504
|
+
* const sl = new SkipList<number, string>();
|
|
3505
|
+
* console.log(sl.isEmpty()); // true;
|
|
3506
|
+
*/
|
|
3507
|
+
isEmpty() {
|
|
3508
|
+
return this._size === 0;
|
|
2039
3509
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
3510
|
+
/**
|
|
3511
|
+
* Remove all entries
|
|
3512
|
+
|
|
3513
|
+
|
|
3514
|
+
|
|
3515
|
+
|
|
3516
|
+
|
|
3517
|
+
|
|
3518
|
+
|
|
3519
|
+
|
|
3520
|
+
|
|
3521
|
+
|
|
3522
|
+
|
|
3523
|
+
|
|
3524
|
+
|
|
3525
|
+
|
|
3526
|
+
|
|
3527
|
+
|
|
3528
|
+
|
|
3529
|
+
|
|
3530
|
+
|
|
3531
|
+
|
|
3532
|
+
|
|
3533
|
+
|
|
3534
|
+
|
|
3535
|
+
|
|
3536
|
+
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
* @example
|
|
3542
|
+
* // Remove all entries
|
|
3543
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3544
|
+
* sl.clear();
|
|
3545
|
+
* console.log(sl.isEmpty()); // true;
|
|
3546
|
+
*/
|
|
3547
|
+
clear() {
|
|
3548
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
3549
|
+
this._level = 0;
|
|
3550
|
+
this._size = 0;
|
|
3551
|
+
}
|
|
3552
|
+
/**
|
|
3553
|
+
* Create independent copy
|
|
3554
|
+
|
|
3555
|
+
|
|
3556
|
+
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
|
|
3560
|
+
|
|
3561
|
+
|
|
3562
|
+
|
|
3563
|
+
|
|
3564
|
+
|
|
3565
|
+
|
|
3566
|
+
|
|
3567
|
+
|
|
3568
|
+
|
|
3569
|
+
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
|
|
3573
|
+
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
|
|
3577
|
+
|
|
3578
|
+
|
|
3579
|
+
|
|
3580
|
+
|
|
3581
|
+
|
|
3582
|
+
|
|
3583
|
+
* @example
|
|
3584
|
+
* // Create independent copy
|
|
3585
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3586
|
+
* const copy = sl.clone();
|
|
3587
|
+
* copy.delete(1);
|
|
3588
|
+
* console.log(sl.has(1)); // true;
|
|
3589
|
+
*/
|
|
3590
|
+
clone() {
|
|
3591
|
+
return new _SkipList(this, {
|
|
3592
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
3593
|
+
maxLevel: this._maxLevel,
|
|
3594
|
+
probability: this._probability
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
// ─── Core CRUD ───────────────────────────────────────────────
|
|
3598
|
+
/**
|
|
3599
|
+
* Insert or update a key-value pair. Returns `this` for chaining.
|
|
3600
|
+
* Unique keys only — if key exists, value is updated in place.
|
|
3601
|
+
|
|
3602
|
+
|
|
3603
|
+
|
|
3604
|
+
|
|
3605
|
+
|
|
3606
|
+
|
|
3607
|
+
|
|
3608
|
+
|
|
3609
|
+
|
|
3610
|
+
|
|
3611
|
+
|
|
3612
|
+
|
|
3613
|
+
|
|
3614
|
+
|
|
3615
|
+
|
|
3616
|
+
|
|
3617
|
+
|
|
3618
|
+
|
|
3619
|
+
|
|
3620
|
+
|
|
3621
|
+
|
|
3622
|
+
|
|
3623
|
+
|
|
3624
|
+
|
|
3625
|
+
|
|
3626
|
+
|
|
3627
|
+
|
|
3628
|
+
|
|
3629
|
+
|
|
3630
|
+
|
|
3631
|
+
|
|
3632
|
+
|
|
3633
|
+
* @example
|
|
3634
|
+
* // In-memory sorted key-value store
|
|
3635
|
+
* const store = new SkipList<number, string>();
|
|
3636
|
+
*
|
|
3637
|
+
* store.set(3, 'three');
|
|
3638
|
+
* store.set(1, 'one');
|
|
3639
|
+
* store.set(5, 'five');
|
|
3640
|
+
* store.set(2, 'two');
|
|
3641
|
+
*
|
|
3642
|
+
* console.log(store.get(3)); // 'three';
|
|
3643
|
+
* console.log(store.get(1)); // 'one';
|
|
3644
|
+
* console.log(store.get(5)); // 'five';
|
|
3645
|
+
*
|
|
3646
|
+
* // Update existing key
|
|
3647
|
+
* store.set(3, 'THREE');
|
|
3648
|
+
* console.log(store.get(3)); // 'THREE';
|
|
3649
|
+
*/
|
|
3650
|
+
set(key, value) {
|
|
3651
|
+
const cmp = __privateGet(this, _comparator);
|
|
3652
|
+
const update = this._findUpdate(key);
|
|
3653
|
+
const existing = update[0].forward[0];
|
|
3654
|
+
if (existing && cmp(existing.key, key) === 0) {
|
|
3655
|
+
existing.value = value;
|
|
3656
|
+
return this;
|
|
3657
|
+
}
|
|
3658
|
+
const newLevel = this._randomLevel();
|
|
3659
|
+
const newNode = new SkipListNode(key, value, newLevel);
|
|
3660
|
+
if (newLevel > this._level) {
|
|
3661
|
+
for (let i = this._level; i < newLevel; i++) {
|
|
3662
|
+
update[i] = this._head;
|
|
2047
3663
|
}
|
|
2048
|
-
|
|
3664
|
+
this._level = newLevel;
|
|
2049
3665
|
}
|
|
2050
|
-
for (let i = 0; i <
|
|
3666
|
+
for (let i = 0; i < newLevel; i++) {
|
|
2051
3667
|
newNode.forward[i] = update[i].forward[i];
|
|
2052
3668
|
update[i].forward[i] = newNode;
|
|
2053
3669
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
}
|
|
3670
|
+
this._size++;
|
|
3671
|
+
return this;
|
|
2057
3672
|
}
|
|
3673
|
+
/**
|
|
3674
|
+
* Get the value for a key, or `undefined` if not found.
|
|
3675
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
3676
|
+
|
|
3677
|
+
|
|
3678
|
+
|
|
3679
|
+
|
|
3680
|
+
|
|
3681
|
+
|
|
3682
|
+
|
|
3683
|
+
|
|
3684
|
+
|
|
3685
|
+
|
|
3686
|
+
|
|
3687
|
+
|
|
3688
|
+
|
|
3689
|
+
|
|
3690
|
+
|
|
3691
|
+
|
|
3692
|
+
|
|
3693
|
+
|
|
3694
|
+
|
|
3695
|
+
|
|
3696
|
+
|
|
3697
|
+
|
|
3698
|
+
|
|
3699
|
+
|
|
3700
|
+
|
|
3701
|
+
|
|
3702
|
+
|
|
3703
|
+
|
|
3704
|
+
|
|
3705
|
+
|
|
3706
|
+
|
|
3707
|
+
|
|
3708
|
+
* @example
|
|
3709
|
+
* // Building a sorted index
|
|
3710
|
+
* type Product = { id: number; name: string; price: number };
|
|
3711
|
+
* const products: Product[] = [
|
|
3712
|
+
* { id: 1, name: 'Widget', price: 25 },
|
|
3713
|
+
* { id: 2, name: 'Gadget', price: 50 },
|
|
3714
|
+
* { id: 3, name: 'Doohickey', price: 15 }
|
|
3715
|
+
* ];
|
|
3716
|
+
*
|
|
3717
|
+
* const index = new SkipList<number, Product, Product>(products, {
|
|
3718
|
+
* toEntryFn: (p: Product) => [p.price, p]
|
|
3719
|
+
* });
|
|
3720
|
+
*
|
|
3721
|
+
* // Iterate in sorted order by price
|
|
3722
|
+
* const names = [...index.values()].map(p => p!.name);
|
|
3723
|
+
* console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
|
|
3724
|
+
*
|
|
3725
|
+
* // Range search: products between $20 and $60
|
|
3726
|
+
* const range = index.rangeSearch([20, 60]);
|
|
3727
|
+
* console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
|
|
3728
|
+
*/
|
|
2058
3729
|
get(key) {
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
while (current.forward[i] && current.forward[i].key < key) {
|
|
2062
|
-
current = current.forward[i];
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
current = current.forward[0];
|
|
2066
|
-
if (current && current.key === key) {
|
|
2067
|
-
return current.value;
|
|
2068
|
-
}
|
|
2069
|
-
return void 0;
|
|
3730
|
+
const node = this._findNode(key);
|
|
3731
|
+
return node ? node.value : void 0;
|
|
2070
3732
|
}
|
|
3733
|
+
/**
|
|
3734
|
+
* Check if a key exists.
|
|
3735
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
3736
|
+
|
|
3737
|
+
|
|
3738
|
+
|
|
3739
|
+
|
|
3740
|
+
|
|
3741
|
+
|
|
3742
|
+
|
|
3743
|
+
|
|
3744
|
+
|
|
3745
|
+
|
|
3746
|
+
|
|
3747
|
+
|
|
3748
|
+
|
|
3749
|
+
|
|
3750
|
+
|
|
3751
|
+
|
|
3752
|
+
|
|
3753
|
+
|
|
3754
|
+
|
|
3755
|
+
|
|
3756
|
+
|
|
3757
|
+
|
|
3758
|
+
|
|
3759
|
+
|
|
3760
|
+
|
|
3761
|
+
|
|
3762
|
+
|
|
3763
|
+
|
|
3764
|
+
|
|
3765
|
+
|
|
3766
|
+
|
|
3767
|
+
|
|
3768
|
+
* @example
|
|
3769
|
+
* // Check key existence
|
|
3770
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
|
|
3771
|
+
* console.log(sl.has(3)); // true;
|
|
3772
|
+
* console.log(sl.has(4)); // false;
|
|
3773
|
+
*/
|
|
2071
3774
|
has(key) {
|
|
2072
|
-
return this.
|
|
3775
|
+
return this._findNode(key) !== void 0;
|
|
2073
3776
|
}
|
|
3777
|
+
/**
|
|
3778
|
+
* Delete a key. Returns `true` if the key was found and removed.
|
|
3779
|
+
|
|
3780
|
+
|
|
3781
|
+
|
|
3782
|
+
|
|
3783
|
+
|
|
3784
|
+
|
|
3785
|
+
|
|
3786
|
+
|
|
3787
|
+
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+
|
|
3791
|
+
|
|
3792
|
+
|
|
3793
|
+
|
|
3794
|
+
|
|
3795
|
+
|
|
3796
|
+
|
|
3797
|
+
|
|
3798
|
+
|
|
3799
|
+
|
|
3800
|
+
|
|
3801
|
+
|
|
3802
|
+
|
|
3803
|
+
|
|
3804
|
+
|
|
3805
|
+
|
|
3806
|
+
|
|
3807
|
+
|
|
3808
|
+
|
|
3809
|
+
|
|
3810
|
+
|
|
3811
|
+
* @example
|
|
3812
|
+
* // Fast lookup with deletion
|
|
3813
|
+
* const cache = new SkipList<string, number>();
|
|
3814
|
+
*
|
|
3815
|
+
* cache.set('alpha', 1);
|
|
3816
|
+
* cache.set('beta', 2);
|
|
3817
|
+
* cache.set('gamma', 3);
|
|
3818
|
+
*
|
|
3819
|
+
* console.log(cache.has('beta')); // true;
|
|
3820
|
+
* cache.delete('beta');
|
|
3821
|
+
* console.log(cache.has('beta')); // false;
|
|
3822
|
+
* console.log(cache.size); // 2;
|
|
3823
|
+
*/
|
|
2074
3824
|
delete(key) {
|
|
2075
|
-
const
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
3825
|
+
const cmp = __privateGet(this, _comparator);
|
|
3826
|
+
const update = this._findUpdate(key);
|
|
3827
|
+
const target = update[0].forward[0];
|
|
3828
|
+
if (!target || cmp(target.key, key) !== 0) return false;
|
|
3829
|
+
for (let i = 0; i < this._level; i++) {
|
|
3830
|
+
if (update[i].forward[i] !== target) break;
|
|
3831
|
+
update[i].forward[i] = target.forward[i];
|
|
3832
|
+
}
|
|
3833
|
+
while (this._level > 0 && !this._head.forward[this._level - 1]) {
|
|
3834
|
+
this._level--;
|
|
3835
|
+
}
|
|
3836
|
+
this._size--;
|
|
3837
|
+
return true;
|
|
3838
|
+
}
|
|
3839
|
+
// ─── Navigation ──────────────────────────────────────────────
|
|
3840
|
+
/**
|
|
3841
|
+
* Returns the first (smallest key) entry, or `undefined` if empty.
|
|
3842
|
+
|
|
3843
|
+
|
|
3844
|
+
|
|
3845
|
+
|
|
3846
|
+
|
|
3847
|
+
|
|
3848
|
+
|
|
3849
|
+
|
|
3850
|
+
|
|
3851
|
+
|
|
3852
|
+
|
|
3853
|
+
|
|
3854
|
+
|
|
3855
|
+
|
|
3856
|
+
|
|
3857
|
+
|
|
3858
|
+
|
|
3859
|
+
|
|
3860
|
+
|
|
3861
|
+
|
|
3862
|
+
|
|
3863
|
+
|
|
3864
|
+
|
|
3865
|
+
|
|
3866
|
+
|
|
3867
|
+
|
|
3868
|
+
|
|
3869
|
+
|
|
3870
|
+
|
|
3871
|
+
|
|
3872
|
+
|
|
3873
|
+
|
|
3874
|
+
* @example
|
|
3875
|
+
* // Access the minimum entry
|
|
3876
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3877
|
+
* console.log(sl.first()); // [1, 'a'];
|
|
3878
|
+
*/
|
|
3879
|
+
first() {
|
|
3880
|
+
const node = this._head.forward[0];
|
|
3881
|
+
return node ? [node.key, node.value] : void 0;
|
|
3882
|
+
}
|
|
3883
|
+
/**
|
|
3884
|
+
* Returns the last (largest key) entry, or `undefined` if empty.
|
|
3885
|
+
|
|
3886
|
+
|
|
3887
|
+
|
|
3888
|
+
|
|
3889
|
+
|
|
3890
|
+
|
|
3891
|
+
|
|
3892
|
+
|
|
3893
|
+
|
|
3894
|
+
|
|
3895
|
+
|
|
3896
|
+
|
|
3897
|
+
|
|
3898
|
+
|
|
3899
|
+
|
|
3900
|
+
|
|
3901
|
+
|
|
3902
|
+
|
|
3903
|
+
|
|
3904
|
+
|
|
3905
|
+
|
|
3906
|
+
|
|
3907
|
+
|
|
3908
|
+
|
|
3909
|
+
|
|
3910
|
+
|
|
3911
|
+
|
|
3912
|
+
|
|
3913
|
+
|
|
3914
|
+
|
|
3915
|
+
|
|
3916
|
+
|
|
3917
|
+
* @example
|
|
3918
|
+
* // Access the maximum entry
|
|
3919
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3920
|
+
* console.log(sl.last()); // [5, 'e'];
|
|
3921
|
+
*/
|
|
3922
|
+
last() {
|
|
3923
|
+
let current = this._head;
|
|
3924
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3925
|
+
while (current.forward[i]) {
|
|
2079
3926
|
current = current.forward[i];
|
|
2080
3927
|
}
|
|
2081
|
-
update[i] = current;
|
|
2082
3928
|
}
|
|
2083
|
-
current
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
3929
|
+
return current === this._head ? void 0 : [current.key, current.value];
|
|
3930
|
+
}
|
|
3931
|
+
/**
|
|
3932
|
+
* Remove and return the first (smallest key) entry.
|
|
3933
|
+
|
|
3934
|
+
|
|
3935
|
+
|
|
3936
|
+
|
|
3937
|
+
|
|
3938
|
+
|
|
3939
|
+
|
|
3940
|
+
|
|
3941
|
+
|
|
3942
|
+
|
|
3943
|
+
|
|
3944
|
+
|
|
3945
|
+
|
|
3946
|
+
|
|
3947
|
+
|
|
3948
|
+
|
|
3949
|
+
|
|
3950
|
+
|
|
3951
|
+
|
|
3952
|
+
|
|
3953
|
+
|
|
3954
|
+
|
|
3955
|
+
|
|
3956
|
+
|
|
3957
|
+
|
|
3958
|
+
|
|
3959
|
+
|
|
3960
|
+
|
|
3961
|
+
|
|
3962
|
+
* @example
|
|
3963
|
+
* // Remove and return smallest
|
|
3964
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3965
|
+
* console.log(sl.pollFirst()); // [1, 'a'];
|
|
3966
|
+
* console.log(sl.size); // 2;
|
|
3967
|
+
*/
|
|
3968
|
+
pollFirst() {
|
|
3969
|
+
const entry = this.first();
|
|
3970
|
+
if (!entry) return void 0;
|
|
3971
|
+
this.delete(entry[0]);
|
|
3972
|
+
return entry;
|
|
3973
|
+
}
|
|
3974
|
+
/**
|
|
3975
|
+
* Remove and return the last (largest key) entry.
|
|
3976
|
+
|
|
3977
|
+
|
|
3978
|
+
|
|
3979
|
+
|
|
3980
|
+
|
|
3981
|
+
|
|
3982
|
+
|
|
3983
|
+
|
|
3984
|
+
|
|
3985
|
+
|
|
3986
|
+
|
|
3987
|
+
|
|
3988
|
+
|
|
3989
|
+
|
|
3990
|
+
|
|
3991
|
+
|
|
3992
|
+
|
|
3993
|
+
|
|
3994
|
+
|
|
3995
|
+
|
|
3996
|
+
|
|
3997
|
+
|
|
3998
|
+
|
|
3999
|
+
|
|
4000
|
+
|
|
4001
|
+
|
|
4002
|
+
|
|
4003
|
+
|
|
4004
|
+
|
|
4005
|
+
* @example
|
|
4006
|
+
* // Remove and return largest
|
|
4007
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
4008
|
+
* console.log(sl.pollLast()); // [3, 'c'];
|
|
4009
|
+
* console.log(sl.size); // 2;
|
|
4010
|
+
*/
|
|
4011
|
+
pollLast() {
|
|
4012
|
+
const entry = this.last();
|
|
4013
|
+
if (!entry) return void 0;
|
|
4014
|
+
this.delete(entry[0]);
|
|
4015
|
+
return entry;
|
|
4016
|
+
}
|
|
4017
|
+
/**
|
|
4018
|
+
* Least entry ≥ key, or `undefined`.
|
|
4019
|
+
|
|
4020
|
+
|
|
4021
|
+
|
|
4022
|
+
|
|
4023
|
+
|
|
4024
|
+
|
|
4025
|
+
|
|
4026
|
+
|
|
4027
|
+
|
|
4028
|
+
|
|
4029
|
+
|
|
4030
|
+
|
|
4031
|
+
|
|
4032
|
+
|
|
4033
|
+
|
|
4034
|
+
|
|
4035
|
+
|
|
4036
|
+
|
|
4037
|
+
|
|
4038
|
+
|
|
4039
|
+
|
|
4040
|
+
|
|
4041
|
+
|
|
4042
|
+
|
|
4043
|
+
|
|
4044
|
+
|
|
4045
|
+
|
|
4046
|
+
|
|
4047
|
+
|
|
4048
|
+
|
|
4049
|
+
|
|
4050
|
+
|
|
4051
|
+
* @example
|
|
4052
|
+
* // Least entry ≥ key
|
|
4053
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4054
|
+
* console.log(sl.ceiling(15)); // [20, 'b'];
|
|
4055
|
+
* console.log(sl.ceiling(20)); // [20, 'b'];
|
|
4056
|
+
*/
|
|
4057
|
+
ceiling(key) {
|
|
4058
|
+
const cmp = __privateGet(this, _comparator);
|
|
4059
|
+
let current = this._head;
|
|
4060
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4061
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4062
|
+
current = current.forward[i];
|
|
2090
4063
|
}
|
|
2091
|
-
|
|
2092
|
-
|
|
4064
|
+
}
|
|
4065
|
+
const node = current.forward[0];
|
|
4066
|
+
return node ? [node.key, node.value] : void 0;
|
|
4067
|
+
}
|
|
4068
|
+
/**
|
|
4069
|
+
* Greatest entry ≤ key, or `undefined`.
|
|
4070
|
+
|
|
4071
|
+
|
|
4072
|
+
|
|
4073
|
+
|
|
4074
|
+
|
|
4075
|
+
|
|
4076
|
+
|
|
4077
|
+
|
|
4078
|
+
|
|
4079
|
+
|
|
4080
|
+
|
|
4081
|
+
|
|
4082
|
+
|
|
4083
|
+
|
|
4084
|
+
|
|
4085
|
+
|
|
4086
|
+
|
|
4087
|
+
|
|
4088
|
+
|
|
4089
|
+
|
|
4090
|
+
|
|
4091
|
+
|
|
4092
|
+
|
|
4093
|
+
|
|
4094
|
+
|
|
4095
|
+
|
|
4096
|
+
|
|
4097
|
+
|
|
4098
|
+
|
|
4099
|
+
|
|
4100
|
+
|
|
4101
|
+
|
|
4102
|
+
* @example
|
|
4103
|
+
* // Greatest entry ≤ key
|
|
4104
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4105
|
+
* console.log(sl.floor(25)); // [20, 'b'];
|
|
4106
|
+
* console.log(sl.floor(5)); // undefined;
|
|
4107
|
+
*/
|
|
4108
|
+
floor(key) {
|
|
4109
|
+
const cmp = __privateGet(this, _comparator);
|
|
4110
|
+
let current = this._head;
|
|
4111
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4112
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
4113
|
+
current = current.forward[i];
|
|
2093
4114
|
}
|
|
2094
|
-
return true;
|
|
2095
4115
|
}
|
|
2096
|
-
|
|
4116
|
+
const result = current === this._head ? void 0 : current;
|
|
4117
|
+
if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
|
|
4118
|
+
return void 0;
|
|
2097
4119
|
}
|
|
4120
|
+
/**
|
|
4121
|
+
* Least entry strictly > key, or `undefined`.
|
|
4122
|
+
|
|
4123
|
+
|
|
4124
|
+
|
|
4125
|
+
|
|
4126
|
+
|
|
4127
|
+
|
|
4128
|
+
|
|
4129
|
+
|
|
4130
|
+
|
|
4131
|
+
|
|
4132
|
+
|
|
4133
|
+
|
|
4134
|
+
|
|
4135
|
+
|
|
4136
|
+
|
|
4137
|
+
|
|
4138
|
+
|
|
4139
|
+
|
|
4140
|
+
|
|
4141
|
+
|
|
4142
|
+
|
|
4143
|
+
|
|
4144
|
+
|
|
4145
|
+
|
|
4146
|
+
|
|
4147
|
+
|
|
4148
|
+
|
|
4149
|
+
|
|
4150
|
+
|
|
4151
|
+
* @example
|
|
4152
|
+
* // Strictly greater entry
|
|
4153
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4154
|
+
* console.log(sl.higher(15)); // [20, 'b'];
|
|
4155
|
+
* console.log(sl.higher(30)); // undefined;
|
|
4156
|
+
*/
|
|
2098
4157
|
higher(key) {
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
4158
|
+
const cmp = __privateGet(this, _comparator);
|
|
4159
|
+
let current = this._head;
|
|
4160
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4161
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
2102
4162
|
current = current.forward[i];
|
|
2103
4163
|
}
|
|
2104
4164
|
}
|
|
2105
|
-
const
|
|
2106
|
-
return
|
|
4165
|
+
const node = current.forward[0];
|
|
4166
|
+
return node ? [node.key, node.value] : void 0;
|
|
2107
4167
|
}
|
|
4168
|
+
/**
|
|
4169
|
+
* Greatest entry strictly < key, or `undefined`.
|
|
4170
|
+
|
|
4171
|
+
|
|
4172
|
+
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
|
|
4192
|
+
|
|
4193
|
+
|
|
4194
|
+
|
|
4195
|
+
|
|
4196
|
+
|
|
4197
|
+
|
|
4198
|
+
|
|
4199
|
+
* @example
|
|
4200
|
+
* // Strictly less entry
|
|
4201
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4202
|
+
* console.log(sl.lower(25)); // [20, 'b'];
|
|
4203
|
+
* console.log(sl.lower(10)); // undefined;
|
|
4204
|
+
*/
|
|
2108
4205
|
lower(key) {
|
|
2109
|
-
|
|
2110
|
-
let
|
|
2111
|
-
|
|
2112
|
-
|
|
4206
|
+
const cmp = __privateGet(this, _comparator);
|
|
4207
|
+
let current = this._head;
|
|
4208
|
+
let result;
|
|
4209
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4210
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2113
4211
|
current = current.forward[i];
|
|
2114
4212
|
}
|
|
2115
|
-
if (current.key <
|
|
2116
|
-
|
|
4213
|
+
if (current !== this._head && cmp(current.key, key) < 0) {
|
|
4214
|
+
result = current;
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
return result ? [result.key, result.value] : void 0;
|
|
4218
|
+
}
|
|
4219
|
+
/**
|
|
4220
|
+
* Returns entries within the given key range.
|
|
4221
|
+
|
|
4222
|
+
|
|
4223
|
+
|
|
4224
|
+
|
|
4225
|
+
|
|
4226
|
+
|
|
4227
|
+
|
|
4228
|
+
|
|
4229
|
+
|
|
4230
|
+
|
|
4231
|
+
|
|
4232
|
+
|
|
4233
|
+
|
|
4234
|
+
|
|
4235
|
+
|
|
4236
|
+
|
|
4237
|
+
|
|
4238
|
+
|
|
4239
|
+
|
|
4240
|
+
|
|
4241
|
+
|
|
4242
|
+
|
|
4243
|
+
|
|
4244
|
+
|
|
4245
|
+
|
|
4246
|
+
|
|
4247
|
+
|
|
4248
|
+
|
|
4249
|
+
|
|
4250
|
+
|
|
4251
|
+
|
|
4252
|
+
|
|
4253
|
+
* @example
|
|
4254
|
+
* // Find entries in a range
|
|
4255
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
|
|
4256
|
+
* const result = sl.rangeSearch([2, 4]);
|
|
4257
|
+
* console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
4258
|
+
*/
|
|
4259
|
+
rangeSearch(range, options = {}) {
|
|
4260
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
4261
|
+
const [low, high] = range;
|
|
4262
|
+
const cmp = __privateGet(this, _comparator);
|
|
4263
|
+
const out = [];
|
|
4264
|
+
let current = this._head;
|
|
4265
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4266
|
+
while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
|
|
4267
|
+
current = current.forward[i];
|
|
2117
4268
|
}
|
|
2118
4269
|
}
|
|
2119
|
-
|
|
4270
|
+
current = current.forward[0];
|
|
4271
|
+
while (current) {
|
|
4272
|
+
const cmpHigh = cmp(current.key, high);
|
|
4273
|
+
if (cmpHigh > 0) break;
|
|
4274
|
+
if (cmpHigh === 0 && !highInclusive) break;
|
|
4275
|
+
const cmpLow = cmp(current.key, low);
|
|
4276
|
+
if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
|
|
4277
|
+
out.push([current.key, current.value]);
|
|
4278
|
+
}
|
|
4279
|
+
current = current.forward[0];
|
|
4280
|
+
}
|
|
4281
|
+
return out;
|
|
4282
|
+
}
|
|
4283
|
+
// ─── Functional (overrides) ──────────────────────────────────
|
|
4284
|
+
/**
|
|
4285
|
+
* Creates a new SkipList with entries transformed by callback.
|
|
4286
|
+
|
|
4287
|
+
|
|
4288
|
+
|
|
4289
|
+
|
|
4290
|
+
|
|
4291
|
+
|
|
4292
|
+
|
|
4293
|
+
|
|
4294
|
+
|
|
4295
|
+
|
|
4296
|
+
|
|
4297
|
+
|
|
4298
|
+
|
|
4299
|
+
|
|
4300
|
+
|
|
4301
|
+
|
|
4302
|
+
|
|
4303
|
+
|
|
4304
|
+
|
|
4305
|
+
|
|
4306
|
+
|
|
4307
|
+
|
|
4308
|
+
|
|
4309
|
+
|
|
4310
|
+
|
|
4311
|
+
|
|
4312
|
+
|
|
4313
|
+
|
|
4314
|
+
|
|
4315
|
+
* @example
|
|
4316
|
+
* // Transform entries
|
|
4317
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
4318
|
+
* const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
|
|
4319
|
+
* console.log([...mapped.values()]); // ['A', 'B'];
|
|
4320
|
+
*/
|
|
4321
|
+
map(callback, options) {
|
|
4322
|
+
const out = new _SkipList([], options != null ? options : {});
|
|
4323
|
+
let i = 0;
|
|
4324
|
+
for (const [k, v] of this) {
|
|
4325
|
+
const [nk, nv] = callback(v, k, i++, this);
|
|
4326
|
+
out.set(nk, nv);
|
|
4327
|
+
}
|
|
4328
|
+
return out;
|
|
4329
|
+
}
|
|
4330
|
+
/**
|
|
4331
|
+
* Creates a new SkipList with entries that pass the predicate.
|
|
4332
|
+
|
|
4333
|
+
|
|
4334
|
+
|
|
4335
|
+
|
|
4336
|
+
|
|
4337
|
+
|
|
4338
|
+
|
|
4339
|
+
|
|
4340
|
+
|
|
4341
|
+
|
|
4342
|
+
|
|
4343
|
+
|
|
4344
|
+
|
|
4345
|
+
|
|
4346
|
+
|
|
4347
|
+
|
|
4348
|
+
|
|
4349
|
+
|
|
4350
|
+
|
|
4351
|
+
|
|
4352
|
+
|
|
4353
|
+
|
|
4354
|
+
|
|
4355
|
+
|
|
4356
|
+
|
|
4357
|
+
|
|
4358
|
+
|
|
4359
|
+
|
|
4360
|
+
|
|
4361
|
+
* @example
|
|
4362
|
+
* // Filter entries
|
|
4363
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
4364
|
+
* const result = sl.filter((v, k) => k > 1);
|
|
4365
|
+
* console.log(result.size); // 2;
|
|
4366
|
+
*/
|
|
4367
|
+
filter(callbackfn, thisArg) {
|
|
4368
|
+
const out = new _SkipList([], {
|
|
4369
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
4370
|
+
maxLevel: this._maxLevel,
|
|
4371
|
+
probability: this._probability
|
|
4372
|
+
});
|
|
4373
|
+
let i = 0;
|
|
4374
|
+
for (const [k, v] of this) {
|
|
4375
|
+
const ok = callbackfn.call(thisArg, v, k, i++, this);
|
|
4376
|
+
if (ok) out.set(k, v);
|
|
4377
|
+
}
|
|
4378
|
+
return out;
|
|
4379
|
+
}
|
|
4380
|
+
// ─── Iterator (required by IterableEntryBase) ────────────────
|
|
4381
|
+
_getIterator() {
|
|
4382
|
+
const head = this._head;
|
|
4383
|
+
return (function* () {
|
|
4384
|
+
let node = head.forward[0];
|
|
4385
|
+
while (node) {
|
|
4386
|
+
yield [node.key, node.value];
|
|
4387
|
+
node = node.forward[0];
|
|
4388
|
+
}
|
|
4389
|
+
})();
|
|
4390
|
+
}
|
|
4391
|
+
// ─── Internal helpers ────────────────────────────────────────
|
|
4392
|
+
/**
|
|
4393
|
+
* Finds the update array (predecessors at each level) for a given key.
|
|
4394
|
+
*/
|
|
4395
|
+
_findUpdate(key) {
|
|
4396
|
+
const cmp = __privateGet(this, _comparator);
|
|
4397
|
+
const update = new Array(this._maxLevel).fill(this._head);
|
|
4398
|
+
let current = this._head;
|
|
4399
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4400
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4401
|
+
current = current.forward[i];
|
|
4402
|
+
}
|
|
4403
|
+
update[i] = current;
|
|
4404
|
+
}
|
|
4405
|
+
return update;
|
|
4406
|
+
}
|
|
4407
|
+
/**
|
|
4408
|
+
* Finds the node for a given key, or undefined.
|
|
4409
|
+
*/
|
|
4410
|
+
_findNode(key) {
|
|
4411
|
+
const cmp = __privateGet(this, _comparator);
|
|
4412
|
+
let current = this._head;
|
|
4413
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4414
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4415
|
+
current = current.forward[i];
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
const candidate = current.forward[0];
|
|
4419
|
+
if (candidate && cmp(candidate.key, key) === 0) return candidate;
|
|
4420
|
+
return void 0;
|
|
2120
4421
|
}
|
|
2121
4422
|
_randomLevel() {
|
|
2122
4423
|
let level = 1;
|
|
2123
|
-
while (Math.random() < this.
|
|
4424
|
+
while (Math.random() < this._probability && level < this._maxLevel) {
|
|
2124
4425
|
level++;
|
|
2125
4426
|
}
|
|
2126
4427
|
return level;
|
|
2127
4428
|
}
|
|
2128
4429
|
};
|
|
4430
|
+
_comparator = new WeakMap();
|
|
4431
|
+
_isDefaultComparator = new WeakMap();
|
|
2129
4432
|
__name(_SkipList, "SkipList");
|
|
2130
4433
|
var SkipList = _SkipList;
|
|
2131
4434
|
/**
|