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
|
@@ -4,6 +4,9 @@ var linkedListTyped = (() => {
|
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __typeError = (msg) => {
|
|
8
|
+
throw TypeError(msg);
|
|
9
|
+
};
|
|
7
10
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
@@ -19,6 +22,10 @@ var linkedListTyped = (() => {
|
|
|
19
22
|
};
|
|
20
23
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
24
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
25
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
26
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
27
|
+
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);
|
|
28
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
22
29
|
|
|
23
30
|
// src/index.ts
|
|
24
31
|
var src_exports = {};
|
|
@@ -34,52 +41,6 @@ var linkedListTyped = (() => {
|
|
|
34
41
|
SkipListNode: () => SkipListNode
|
|
35
42
|
});
|
|
36
43
|
|
|
37
|
-
// src/common/error.ts
|
|
38
|
-
var ERR = {
|
|
39
|
-
// Range / index
|
|
40
|
-
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
41
|
-
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
42
|
-
// Type / argument
|
|
43
|
-
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
44
|
-
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
45
|
-
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
46
|
-
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
47
|
-
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
48
|
-
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
49
|
-
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
50
|
-
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
51
|
-
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
52
|
-
// State / operation
|
|
53
|
-
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
54
|
-
// Matrix
|
|
55
|
-
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
56
|
-
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
57
|
-
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
58
|
-
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
59
|
-
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// src/common/index.ts
|
|
63
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
64
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
65
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
66
|
-
return DFSOperation2;
|
|
67
|
-
})(DFSOperation || {});
|
|
68
|
-
var Range = class {
|
|
69
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
70
|
-
this.low = low;
|
|
71
|
-
this.high = high;
|
|
72
|
-
this.includeLow = includeLow;
|
|
73
|
-
this.includeHigh = includeHigh;
|
|
74
|
-
}
|
|
75
|
-
// Determine whether a key is within the range
|
|
76
|
-
isInRange(key, comparator) {
|
|
77
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
78
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
79
|
-
return lowCheck && highCheck;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
44
|
// src/data-structures/base/iterable-element-base.ts
|
|
84
45
|
var IterableElementBase = class {
|
|
85
46
|
/**
|
|
@@ -102,7 +63,7 @@ var linkedListTyped = (() => {
|
|
|
102
63
|
if (options) {
|
|
103
64
|
const { toElementFn } = options;
|
|
104
65
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
105
|
-
else if (toElementFn) throw new TypeError(
|
|
66
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
106
67
|
}
|
|
107
68
|
}
|
|
108
69
|
/**
|
|
@@ -258,7 +219,7 @@ var linkedListTyped = (() => {
|
|
|
258
219
|
acc = initialValue;
|
|
259
220
|
} else {
|
|
260
221
|
const first = iter.next();
|
|
261
|
-
if (first.done) throw new TypeError(
|
|
222
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
262
223
|
acc = first.value;
|
|
263
224
|
index = 1;
|
|
264
225
|
}
|
|
@@ -786,11 +747,58 @@ var linkedListTyped = (() => {
|
|
|
786
747
|
return list;
|
|
787
748
|
}
|
|
788
749
|
/**
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
750
|
+
* Append an element/node to the tail.
|
|
751
|
+
* @remarks Time O(1), Space O(1)
|
|
752
|
+
* @param elementOrNode - Element or node to append.
|
|
753
|
+
* @returns True when appended.
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
* @example
|
|
787
|
+
* // basic SinglyLinkedList creation and push operation
|
|
788
|
+
* // Create a simple SinglyLinkedList with initial values
|
|
789
|
+
* const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
|
790
|
+
*
|
|
791
|
+
* // Verify the list maintains insertion order
|
|
792
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
793
|
+
*
|
|
794
|
+
* // Check length
|
|
795
|
+
* console.log(list.length); // 5;
|
|
796
|
+
*
|
|
797
|
+
* // Push a new element to the end
|
|
798
|
+
* list.push(6);
|
|
799
|
+
* console.log(list.length); // 6;
|
|
800
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
801
|
+
*/
|
|
794
802
|
push(elementOrNode) {
|
|
795
803
|
const newNode = this._ensureNode(elementOrNode);
|
|
796
804
|
if (!this.head) {
|
|
@@ -804,10 +812,57 @@ var linkedListTyped = (() => {
|
|
|
804
812
|
return true;
|
|
805
813
|
}
|
|
806
814
|
/**
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
815
|
+
* Remove and return the tail element.
|
|
816
|
+
* @remarks Time O(N), Space O(1)
|
|
817
|
+
* @returns Removed element or undefined.
|
|
818
|
+
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
* @example
|
|
851
|
+
* // SinglyLinkedList pop and shift operations
|
|
852
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
853
|
+
*
|
|
854
|
+
* // Pop removes from the end
|
|
855
|
+
* const last = list.pop();
|
|
856
|
+
* console.log(last); // 50;
|
|
857
|
+
*
|
|
858
|
+
* // Shift removes from the beginning
|
|
859
|
+
* const first = list.shift();
|
|
860
|
+
* console.log(first); // 10;
|
|
861
|
+
*
|
|
862
|
+
* // Verify remaining elements
|
|
863
|
+
* console.log([...list]); // [20, 30, 40];
|
|
864
|
+
* console.log(list.length); // 3;
|
|
865
|
+
*/
|
|
811
866
|
pop() {
|
|
812
867
|
var _a;
|
|
813
868
|
if (!this.head) return void 0;
|
|
@@ -827,10 +882,47 @@ var linkedListTyped = (() => {
|
|
|
827
882
|
return value;
|
|
828
883
|
}
|
|
829
884
|
/**
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
885
|
+
* Remove and return the head element.
|
|
886
|
+
* @remarks Time O(1), Space O(1)
|
|
887
|
+
* @returns Removed element or undefined.
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
* @example
|
|
921
|
+
* // Remove from the front
|
|
922
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30]);
|
|
923
|
+
* console.log(list.shift()); // 10;
|
|
924
|
+
* console.log(list.length); // 2;
|
|
925
|
+
*/
|
|
834
926
|
shift() {
|
|
835
927
|
if (!this.head) return void 0;
|
|
836
928
|
const removed = this.head;
|
|
@@ -840,11 +932,63 @@ var linkedListTyped = (() => {
|
|
|
840
932
|
return removed.value;
|
|
841
933
|
}
|
|
842
934
|
/**
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
935
|
+
* Prepend an element/node to the head.
|
|
936
|
+
* @remarks Time O(1), Space O(1)
|
|
937
|
+
* @param elementOrNode - Element or node to prepend.
|
|
938
|
+
* @returns True when prepended.
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
* @example
|
|
972
|
+
* // SinglyLinkedList unshift and forward traversal
|
|
973
|
+
* const list = new SinglyLinkedList<number>([20, 30, 40]);
|
|
974
|
+
*
|
|
975
|
+
* // Unshift adds to the beginning
|
|
976
|
+
* list.unshift(10);
|
|
977
|
+
* console.log([...list]); // [10, 20, 30, 40];
|
|
978
|
+
*
|
|
979
|
+
* // Access elements (forward traversal only for singly linked)
|
|
980
|
+
* const second = list.at(1);
|
|
981
|
+
* console.log(second); // 20;
|
|
982
|
+
*
|
|
983
|
+
* // SinglyLinkedList allows forward iteration only
|
|
984
|
+
* const elements: number[] = [];
|
|
985
|
+
* for (const item of list) {
|
|
986
|
+
* elements.push(item);
|
|
987
|
+
* }
|
|
988
|
+
* console.log(elements); // [10, 20, 30, 40];
|
|
989
|
+
*
|
|
990
|
+
* console.log(list.length); // 4;
|
|
991
|
+
*/
|
|
848
992
|
unshift(elementOrNode) {
|
|
849
993
|
const newNode = this._ensureNode(elementOrNode);
|
|
850
994
|
if (!this.head) {
|
|
@@ -900,11 +1044,49 @@ var linkedListTyped = (() => {
|
|
|
900
1044
|
return void 0;
|
|
901
1045
|
}
|
|
902
1046
|
/**
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1047
|
+
* Get the element at a given index.
|
|
1048
|
+
* @remarks Time O(N), Space O(1)
|
|
1049
|
+
* @param index - Zero-based index.
|
|
1050
|
+
* @returns Element or undefined.
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
* @example
|
|
1084
|
+
* // Access element by index
|
|
1085
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
|
|
1086
|
+
* console.log(list.at(0)); // 'a';
|
|
1087
|
+
* console.log(list.at(2)); // 'c';
|
|
1088
|
+
* console.log(list.at(3)); // 'd';
|
|
1089
|
+
*/
|
|
908
1090
|
at(index) {
|
|
909
1091
|
if (index < 0 || index >= this._length) return void 0;
|
|
910
1092
|
let current = this.head;
|
|
@@ -921,11 +1103,44 @@ var linkedListTyped = (() => {
|
|
|
921
1103
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
922
1104
|
}
|
|
923
1105
|
/**
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1106
|
+
* Get the node reference at a given index.
|
|
1107
|
+
* @remarks Time O(N), Space O(1)
|
|
1108
|
+
* @param index - Zero-based index.
|
|
1109
|
+
* @returns Node or undefined.
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
* @example
|
|
1140
|
+
* // Get node at index
|
|
1141
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1142
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
1143
|
+
*/
|
|
929
1144
|
getNodeAt(index) {
|
|
930
1145
|
if (index < 0 || index >= this._length) return void 0;
|
|
931
1146
|
let current = this.head;
|
|
@@ -933,11 +1148,45 @@ var linkedListTyped = (() => {
|
|
|
933
1148
|
return current;
|
|
934
1149
|
}
|
|
935
1150
|
/**
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1151
|
+
* Delete the element at an index.
|
|
1152
|
+
* @remarks Time O(N), Space O(1)
|
|
1153
|
+
* @param index - Zero-based index.
|
|
1154
|
+
* @returns Removed element or undefined.
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
* @example
|
|
1185
|
+
* // Remove by index
|
|
1186
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1187
|
+
* list.deleteAt(1);
|
|
1188
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
1189
|
+
*/
|
|
941
1190
|
deleteAt(index) {
|
|
942
1191
|
if (index < 0 || index >= this._length) return void 0;
|
|
943
1192
|
if (index === 0) return this.shift();
|
|
@@ -950,11 +1199,45 @@ var linkedListTyped = (() => {
|
|
|
950
1199
|
return value;
|
|
951
1200
|
}
|
|
952
1201
|
/**
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1202
|
+
* Delete the first match by value/node.
|
|
1203
|
+
* @remarks Time O(N), Space O(1)
|
|
1204
|
+
* @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
|
|
1205
|
+
* @returns True if removed.
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
* @example
|
|
1236
|
+
* // Remove first occurrence
|
|
1237
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
|
|
1238
|
+
* list.delete(2);
|
|
1239
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
1240
|
+
*/
|
|
958
1241
|
delete(elementOrNode) {
|
|
959
1242
|
if (elementOrNode === void 0 || !this.head) return false;
|
|
960
1243
|
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
@@ -971,12 +1254,46 @@ var linkedListTyped = (() => {
|
|
|
971
1254
|
return true;
|
|
972
1255
|
}
|
|
973
1256
|
/**
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1257
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
1258
|
+
* @remarks Time O(N), Space O(1)
|
|
1259
|
+
* @param index - Zero-based index.
|
|
1260
|
+
* @param newElementOrNode - Element or node to insert.
|
|
1261
|
+
* @returns True if inserted.
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
* @example
|
|
1292
|
+
* // Insert at index
|
|
1293
|
+
* const list = new SinglyLinkedList<number>([1, 3]);
|
|
1294
|
+
* list.addAt(1, 2);
|
|
1295
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
1296
|
+
*/
|
|
980
1297
|
addAt(index, newElementOrNode) {
|
|
981
1298
|
if (index < 0 || index > this._length) return false;
|
|
982
1299
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1002,28 +1319,133 @@ var linkedListTyped = (() => {
|
|
|
1002
1319
|
return true;
|
|
1003
1320
|
}
|
|
1004
1321
|
/**
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1322
|
+
* Check whether the list is empty.
|
|
1323
|
+
* @remarks Time O(1), Space O(1)
|
|
1324
|
+
* @returns True if length is 0.
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
* @example
|
|
1356
|
+
* // Check empty
|
|
1357
|
+
* console.log(new SinglyLinkedList().isEmpty()); // true;
|
|
1358
|
+
*/
|
|
1009
1359
|
isEmpty() {
|
|
1010
1360
|
return this._length === 0;
|
|
1011
1361
|
}
|
|
1012
1362
|
/**
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1363
|
+
* Remove all nodes and reset length.
|
|
1364
|
+
* @remarks Time O(N), Space O(1)
|
|
1365
|
+
* @returns void
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
* @example
|
|
1397
|
+
* // Remove all
|
|
1398
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1399
|
+
* list.clear();
|
|
1400
|
+
* console.log(list.isEmpty()); // true;
|
|
1401
|
+
*/
|
|
1017
1402
|
clear() {
|
|
1018
1403
|
this._head = void 0;
|
|
1019
1404
|
this._tail = void 0;
|
|
1020
1405
|
this._length = 0;
|
|
1021
1406
|
}
|
|
1022
1407
|
/**
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1408
|
+
* Reverse the list in place.
|
|
1409
|
+
* @remarks Time O(N), Space O(1)
|
|
1410
|
+
* @returns This list.
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
* @example
|
|
1444
|
+
* // Reverse the list in-place
|
|
1445
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
|
|
1446
|
+
* list.reverse();
|
|
1447
|
+
* console.log([...list]); // [4, 3, 2, 1];
|
|
1448
|
+
*/
|
|
1027
1449
|
reverse() {
|
|
1028
1450
|
if (!this.head || this.head === this.tail) return this;
|
|
1029
1451
|
let prev;
|
|
@@ -1198,22 +1620,106 @@ var linkedListTyped = (() => {
|
|
|
1198
1620
|
return false;
|
|
1199
1621
|
}
|
|
1200
1622
|
/**
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1623
|
+
* Deep clone this list (values are copied by reference).
|
|
1624
|
+
* @remarks Time O(N), Space O(N)
|
|
1625
|
+
* @returns A new list with the same element sequence.
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
|
|
1650
|
+
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
|
|
1656
|
+
* @example
|
|
1657
|
+
* // Deep copy
|
|
1658
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1659
|
+
* const copy = list.clone();
|
|
1660
|
+
* copy.pop();
|
|
1661
|
+
* console.log(list.length); // 3;
|
|
1662
|
+
* console.log(copy.length); // 2;
|
|
1663
|
+
*/
|
|
1205
1664
|
clone() {
|
|
1206
1665
|
const out = this._createInstance();
|
|
1207
1666
|
for (const v of this) out.push(v);
|
|
1208
1667
|
return out;
|
|
1209
1668
|
}
|
|
1210
1669
|
/**
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1670
|
+
* Filter values into a new list of the same class.
|
|
1671
|
+
* @remarks Time O(N), Space O(N)
|
|
1672
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
1673
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1674
|
+
* @returns A new list with kept values.
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
* @example
|
|
1708
|
+
* // SinglyLinkedList filter and map operations
|
|
1709
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
1710
|
+
*
|
|
1711
|
+
* // Filter even numbers
|
|
1712
|
+
* const filtered = list.filter(value => value % 2 === 0);
|
|
1713
|
+
* console.log(filtered.length); // 2;
|
|
1714
|
+
*
|
|
1715
|
+
* // Map to double values
|
|
1716
|
+
* const doubled = list.map(value => value * 2);
|
|
1717
|
+
* console.log(doubled.length); // 5;
|
|
1718
|
+
*
|
|
1719
|
+
* // Use reduce to sum
|
|
1720
|
+
* const sum = list.reduce((acc, value) => acc + value, 0);
|
|
1721
|
+
* console.log(sum); // 15;
|
|
1722
|
+
*/
|
|
1217
1723
|
filter(callback, thisArg) {
|
|
1218
1724
|
const out = this._createInstance();
|
|
1219
1725
|
let index = 0;
|
|
@@ -1237,15 +1743,52 @@ var linkedListTyped = (() => {
|
|
|
1237
1743
|
return out;
|
|
1238
1744
|
}
|
|
1239
1745
|
/**
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1746
|
+
* Map values into a new list (possibly different element type).
|
|
1747
|
+
* @remarks Time O(N), Space O(N)
|
|
1748
|
+
* @template EM
|
|
1749
|
+
* @template RM
|
|
1750
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1751
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1752
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1753
|
+
* @returns A new SinglyLinkedList with mapped values.
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
|
|
1767
|
+
|
|
1768
|
+
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
* @example
|
|
1787
|
+
* // Transform elements
|
|
1788
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1789
|
+
* const doubled = list.map(n => n * 2);
|
|
1790
|
+
* console.log([...doubled]); // [2, 4, 6];
|
|
1791
|
+
*/
|
|
1249
1792
|
map(callback, options, thisArg) {
|
|
1250
1793
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1251
1794
|
let index = 0;
|
|
@@ -1516,11 +2059,58 @@ var linkedListTyped = (() => {
|
|
|
1516
2059
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
1517
2060
|
}
|
|
1518
2061
|
/**
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
2062
|
+
* Append an element/node to the tail.
|
|
2063
|
+
* @remarks Time O(1), Space O(1)
|
|
2064
|
+
* @param elementOrNode - Element or node to append.
|
|
2065
|
+
* @returns True when appended.
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
|
|
2074
|
+
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
* @example
|
|
2099
|
+
* // basic DoublyLinkedList creation and push operation
|
|
2100
|
+
* // Create a simple DoublyLinkedList with initial values
|
|
2101
|
+
* const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
|
2102
|
+
*
|
|
2103
|
+
* // Verify the list maintains insertion order
|
|
2104
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
2105
|
+
*
|
|
2106
|
+
* // Check length
|
|
2107
|
+
* console.log(list.length); // 5;
|
|
2108
|
+
*
|
|
2109
|
+
* // Push a new element to the end
|
|
2110
|
+
* list.push(6);
|
|
2111
|
+
* console.log(list.length); // 6;
|
|
2112
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
2113
|
+
*/
|
|
1524
2114
|
push(elementOrNode) {
|
|
1525
2115
|
const newNode = this._ensureNode(elementOrNode);
|
|
1526
2116
|
if (!this.head) {
|
|
@@ -1536,10 +2126,57 @@ var linkedListTyped = (() => {
|
|
|
1536
2126
|
return true;
|
|
1537
2127
|
}
|
|
1538
2128
|
/**
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
2129
|
+
* Remove and return the tail element.
|
|
2130
|
+
* @remarks Time O(1), Space O(1)
|
|
2131
|
+
* @returns Removed element or undefined.
|
|
2132
|
+
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
|
|
2138
|
+
|
|
2139
|
+
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
|
|
2143
|
+
|
|
2144
|
+
|
|
2145
|
+
|
|
2146
|
+
|
|
2147
|
+
|
|
2148
|
+
|
|
2149
|
+
|
|
2150
|
+
|
|
2151
|
+
|
|
2152
|
+
|
|
2153
|
+
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
|
|
2157
|
+
|
|
2158
|
+
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
* @example
|
|
2165
|
+
* // DoublyLinkedList pop and shift operations
|
|
2166
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
2167
|
+
*
|
|
2168
|
+
* // Pop removes from the end
|
|
2169
|
+
* const last = list.pop();
|
|
2170
|
+
* console.log(last); // 50;
|
|
2171
|
+
*
|
|
2172
|
+
* // Shift removes from the beginning
|
|
2173
|
+
* const first = list.shift();
|
|
2174
|
+
* console.log(first); // 10;
|
|
2175
|
+
*
|
|
2176
|
+
* // Verify remaining elements
|
|
2177
|
+
* console.log([...list]); // [20, 30, 40];
|
|
2178
|
+
* console.log(list.length); // 3;
|
|
2179
|
+
*/
|
|
1543
2180
|
pop() {
|
|
1544
2181
|
if (!this.tail) return void 0;
|
|
1545
2182
|
const removed = this.tail;
|
|
@@ -1554,10 +2191,47 @@ var linkedListTyped = (() => {
|
|
|
1554
2191
|
return removed.value;
|
|
1555
2192
|
}
|
|
1556
2193
|
/**
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
2194
|
+
* Remove and return the head element.
|
|
2195
|
+
* @remarks Time O(1), Space O(1)
|
|
2196
|
+
* @returns Removed element or undefined.
|
|
2197
|
+
|
|
2198
|
+
|
|
2199
|
+
|
|
2200
|
+
|
|
2201
|
+
|
|
2202
|
+
|
|
2203
|
+
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
* @example
|
|
2230
|
+
* // Remove from the front
|
|
2231
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2232
|
+
* console.log(list.shift()); // 10;
|
|
2233
|
+
* console.log(list.first); // 20;
|
|
2234
|
+
*/
|
|
1561
2235
|
shift() {
|
|
1562
2236
|
if (!this.head) return void 0;
|
|
1563
2237
|
const removed = this.head;
|
|
@@ -1572,11 +2246,48 @@ var linkedListTyped = (() => {
|
|
|
1572
2246
|
return removed.value;
|
|
1573
2247
|
}
|
|
1574
2248
|
/**
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
2249
|
+
* Prepend an element/node to the head.
|
|
2250
|
+
* @remarks Time O(1), Space O(1)
|
|
2251
|
+
* @param elementOrNode - Element or node to prepend.
|
|
2252
|
+
* @returns True when prepended.
|
|
2253
|
+
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
|
|
2257
|
+
|
|
2258
|
+
|
|
2259
|
+
|
|
2260
|
+
|
|
2261
|
+
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
|
|
2270
|
+
|
|
2271
|
+
|
|
2272
|
+
|
|
2273
|
+
|
|
2274
|
+
|
|
2275
|
+
|
|
2276
|
+
|
|
2277
|
+
|
|
2278
|
+
|
|
2279
|
+
|
|
2280
|
+
|
|
2281
|
+
|
|
2282
|
+
|
|
2283
|
+
|
|
2284
|
+
|
|
2285
|
+
* @example
|
|
2286
|
+
* // Add to the front
|
|
2287
|
+
* const list = new DoublyLinkedList<number>([2, 3]);
|
|
2288
|
+
* list.unshift(1);
|
|
2289
|
+
* console.log([...list]); // [1, 2, 3];
|
|
2290
|
+
*/
|
|
1580
2291
|
unshift(elementOrNode) {
|
|
1581
2292
|
const newNode = this._ensureNode(elementOrNode);
|
|
1582
2293
|
if (!this.head) {
|
|
@@ -1620,11 +2331,48 @@ var linkedListTyped = (() => {
|
|
|
1620
2331
|
return ans;
|
|
1621
2332
|
}
|
|
1622
2333
|
/**
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
2334
|
+
* Get the element at a given index.
|
|
2335
|
+
* @remarks Time O(N), Space O(1)
|
|
2336
|
+
* @param index - Zero-based index.
|
|
2337
|
+
* @returns Element or undefined.
|
|
2338
|
+
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
|
|
2342
|
+
|
|
2343
|
+
|
|
2344
|
+
|
|
2345
|
+
|
|
2346
|
+
|
|
2347
|
+
|
|
2348
|
+
|
|
2349
|
+
|
|
2350
|
+
|
|
2351
|
+
|
|
2352
|
+
|
|
2353
|
+
|
|
2354
|
+
|
|
2355
|
+
|
|
2356
|
+
|
|
2357
|
+
|
|
2358
|
+
|
|
2359
|
+
|
|
2360
|
+
|
|
2361
|
+
|
|
2362
|
+
|
|
2363
|
+
|
|
2364
|
+
|
|
2365
|
+
|
|
2366
|
+
|
|
2367
|
+
|
|
2368
|
+
|
|
2369
|
+
|
|
2370
|
+
* @example
|
|
2371
|
+
* // Access by index
|
|
2372
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2373
|
+
* console.log(list.at(1)); // 'b';
|
|
2374
|
+
* console.log(list.at(2)); // 'c';
|
|
2375
|
+
*/
|
|
1628
2376
|
at(index) {
|
|
1629
2377
|
if (index < 0 || index >= this._length) return void 0;
|
|
1630
2378
|
let current = this.head;
|
|
@@ -1632,11 +2380,44 @@ var linkedListTyped = (() => {
|
|
|
1632
2380
|
return current == null ? void 0 : current.value;
|
|
1633
2381
|
}
|
|
1634
2382
|
/**
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
2383
|
+
* Get the node reference at a given index.
|
|
2384
|
+
* @remarks Time O(N), Space O(1)
|
|
2385
|
+
* @param index - Zero-based index.
|
|
2386
|
+
* @returns Node or undefined.
|
|
2387
|
+
|
|
2388
|
+
|
|
2389
|
+
|
|
2390
|
+
|
|
2391
|
+
|
|
2392
|
+
|
|
2393
|
+
|
|
2394
|
+
|
|
2395
|
+
|
|
2396
|
+
|
|
2397
|
+
|
|
2398
|
+
|
|
2399
|
+
|
|
2400
|
+
|
|
2401
|
+
|
|
2402
|
+
|
|
2403
|
+
|
|
2404
|
+
|
|
2405
|
+
|
|
2406
|
+
|
|
2407
|
+
|
|
2408
|
+
|
|
2409
|
+
|
|
2410
|
+
|
|
2411
|
+
|
|
2412
|
+
|
|
2413
|
+
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
* @example
|
|
2417
|
+
* // Get node at index
|
|
2418
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2419
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
2420
|
+
*/
|
|
1640
2421
|
getNodeAt(index) {
|
|
1641
2422
|
if (index < 0 || index >= this._length) return void 0;
|
|
1642
2423
|
let current = this.head;
|
|
@@ -1675,12 +2456,46 @@ var linkedListTyped = (() => {
|
|
|
1675
2456
|
return void 0;
|
|
1676
2457
|
}
|
|
1677
2458
|
/**
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
2459
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
2460
|
+
* @remarks Time O(N), Space O(1)
|
|
2461
|
+
* @param index - Zero-based index.
|
|
2462
|
+
* @param newElementOrNode - Element or node to insert.
|
|
2463
|
+
* @returns True if inserted.
|
|
2464
|
+
|
|
2465
|
+
|
|
2466
|
+
|
|
2467
|
+
|
|
2468
|
+
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
|
|
2472
|
+
|
|
2473
|
+
|
|
2474
|
+
|
|
2475
|
+
|
|
2476
|
+
|
|
2477
|
+
|
|
2478
|
+
|
|
2479
|
+
|
|
2480
|
+
|
|
2481
|
+
|
|
2482
|
+
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
|
|
2487
|
+
|
|
2488
|
+
|
|
2489
|
+
|
|
2490
|
+
|
|
2491
|
+
|
|
2492
|
+
|
|
2493
|
+
* @example
|
|
2494
|
+
* // Insert at position
|
|
2495
|
+
* const list = new DoublyLinkedList<number>([1, 3]);
|
|
2496
|
+
* list.addAt(1, 2);
|
|
2497
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
2498
|
+
*/
|
|
1684
2499
|
addAt(index, newElementOrNode) {
|
|
1685
2500
|
if (index < 0 || index > this._length) return false;
|
|
1686
2501
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1747,11 +2562,45 @@ var linkedListTyped = (() => {
|
|
|
1747
2562
|
return true;
|
|
1748
2563
|
}
|
|
1749
2564
|
/**
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
2565
|
+
* Delete the element at an index.
|
|
2566
|
+
* @remarks Time O(N), Space O(1)
|
|
2567
|
+
* @param index - Zero-based index.
|
|
2568
|
+
* @returns Removed element or undefined.
|
|
2569
|
+
|
|
2570
|
+
|
|
2571
|
+
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
|
|
2575
|
+
|
|
2576
|
+
|
|
2577
|
+
|
|
2578
|
+
|
|
2579
|
+
|
|
2580
|
+
|
|
2581
|
+
|
|
2582
|
+
|
|
2583
|
+
|
|
2584
|
+
|
|
2585
|
+
|
|
2586
|
+
|
|
2587
|
+
|
|
2588
|
+
|
|
2589
|
+
|
|
2590
|
+
|
|
2591
|
+
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
|
|
2597
|
+
|
|
2598
|
+
* @example
|
|
2599
|
+
* // Remove by index
|
|
2600
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2601
|
+
* list.deleteAt(1);
|
|
2602
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
2603
|
+
*/
|
|
1755
2604
|
deleteAt(index) {
|
|
1756
2605
|
if (index < 0 || index >= this._length) return;
|
|
1757
2606
|
if (index === 0) return this.shift();
|
|
@@ -1765,11 +2614,45 @@ var linkedListTyped = (() => {
|
|
|
1765
2614
|
return removedNode.value;
|
|
1766
2615
|
}
|
|
1767
2616
|
/**
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
2617
|
+
* Delete the first match by value/node.
|
|
2618
|
+
* @remarks Time O(N), Space O(1)
|
|
2619
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
2620
|
+
* @returns True if removed.
|
|
2621
|
+
|
|
2622
|
+
|
|
2623
|
+
|
|
2624
|
+
|
|
2625
|
+
|
|
2626
|
+
|
|
2627
|
+
|
|
2628
|
+
|
|
2629
|
+
|
|
2630
|
+
|
|
2631
|
+
|
|
2632
|
+
|
|
2633
|
+
|
|
2634
|
+
|
|
2635
|
+
|
|
2636
|
+
|
|
2637
|
+
|
|
2638
|
+
|
|
2639
|
+
|
|
2640
|
+
|
|
2641
|
+
|
|
2642
|
+
|
|
2643
|
+
|
|
2644
|
+
|
|
2645
|
+
|
|
2646
|
+
|
|
2647
|
+
|
|
2648
|
+
|
|
2649
|
+
|
|
2650
|
+
* @example
|
|
2651
|
+
* // Remove first occurrence
|
|
2652
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
|
|
2653
|
+
* list.delete(2);
|
|
2654
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
2655
|
+
*/
|
|
1773
2656
|
delete(elementOrNode) {
|
|
1774
2657
|
const node = this.getNode(elementOrNode);
|
|
1775
2658
|
if (!node) return false;
|
|
@@ -1785,29 +2668,131 @@ var linkedListTyped = (() => {
|
|
|
1785
2668
|
return true;
|
|
1786
2669
|
}
|
|
1787
2670
|
/**
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2671
|
+
* Check whether the list is empty.
|
|
2672
|
+
* @remarks Time O(1), Space O(1)
|
|
2673
|
+
* @returns True if length is 0.
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
|
|
2677
|
+
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
|
|
2681
|
+
|
|
2682
|
+
|
|
2683
|
+
|
|
2684
|
+
|
|
2685
|
+
|
|
2686
|
+
|
|
2687
|
+
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
|
|
2696
|
+
|
|
2697
|
+
|
|
2698
|
+
|
|
2699
|
+
|
|
2700
|
+
|
|
2701
|
+
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
* @example
|
|
2705
|
+
* // Check empty
|
|
2706
|
+
* console.log(new DoublyLinkedList().isEmpty()); // true;
|
|
2707
|
+
*/
|
|
1792
2708
|
isEmpty() {
|
|
1793
2709
|
return this._length === 0;
|
|
1794
2710
|
}
|
|
1795
2711
|
/**
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2712
|
+
* Remove all nodes and reset length.
|
|
2713
|
+
* @remarks Time O(N), Space O(1)
|
|
2714
|
+
* @returns void
|
|
2715
|
+
|
|
2716
|
+
|
|
2717
|
+
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
|
|
2735
|
+
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
|
|
2739
|
+
|
|
2740
|
+
|
|
2741
|
+
|
|
2742
|
+
|
|
2743
|
+
|
|
2744
|
+
|
|
2745
|
+
* @example
|
|
2746
|
+
* // Remove all
|
|
2747
|
+
* const list = new DoublyLinkedList<number>([1, 2]);
|
|
2748
|
+
* list.clear();
|
|
2749
|
+
* console.log(list.isEmpty()); // true;
|
|
2750
|
+
*/
|
|
1800
2751
|
clear() {
|
|
1801
2752
|
this._head = void 0;
|
|
1802
2753
|
this._tail = void 0;
|
|
1803
2754
|
this._length = 0;
|
|
1804
2755
|
}
|
|
1805
2756
|
/**
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
2757
|
+
* Find the first value matching a predicate scanning forward.
|
|
2758
|
+
* @remarks Time O(N), Space O(1)
|
|
2759
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2760
|
+
* @returns Matched value or undefined.
|
|
2761
|
+
|
|
2762
|
+
|
|
2763
|
+
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
|
|
2768
|
+
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
|
|
2772
|
+
|
|
2773
|
+
|
|
2774
|
+
|
|
2775
|
+
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
|
|
2785
|
+
|
|
2786
|
+
|
|
2787
|
+
|
|
2788
|
+
|
|
2789
|
+
|
|
2790
|
+
* @example
|
|
2791
|
+
* // Search with predicate
|
|
2792
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2793
|
+
* const found = list.search(node => node.value > 15);
|
|
2794
|
+
* console.log(found); // 20;
|
|
2795
|
+
*/
|
|
1811
2796
|
search(elementNodeOrPredicate) {
|
|
1812
2797
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1813
2798
|
let current = this.head;
|
|
@@ -1818,11 +2803,46 @@ var linkedListTyped = (() => {
|
|
|
1818
2803
|
return void 0;
|
|
1819
2804
|
}
|
|
1820
2805
|
/**
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
2806
|
+
* Find the first value matching a predicate scanning backward.
|
|
2807
|
+
* @remarks Time O(N), Space O(1)
|
|
2808
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2809
|
+
* @returns Matched value or undefined.
|
|
2810
|
+
|
|
2811
|
+
|
|
2812
|
+
|
|
2813
|
+
|
|
2814
|
+
|
|
2815
|
+
|
|
2816
|
+
|
|
2817
|
+
|
|
2818
|
+
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
|
|
2822
|
+
|
|
2823
|
+
|
|
2824
|
+
|
|
2825
|
+
|
|
2826
|
+
|
|
2827
|
+
|
|
2828
|
+
|
|
2829
|
+
|
|
2830
|
+
|
|
2831
|
+
|
|
2832
|
+
|
|
2833
|
+
|
|
2834
|
+
|
|
2835
|
+
|
|
2836
|
+
|
|
2837
|
+
|
|
2838
|
+
|
|
2839
|
+
* @example
|
|
2840
|
+
* // Find value scanning from tail
|
|
2841
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
|
|
2842
|
+
* // getBackward scans from tail to head, returns first match
|
|
2843
|
+
* const found = list.getBackward(node => node.value < 4);
|
|
2844
|
+
* console.log(found); // 3;
|
|
2845
|
+
*/
|
|
1826
2846
|
getBackward(elementNodeOrPredicate) {
|
|
1827
2847
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1828
2848
|
let current = this.tail;
|
|
@@ -1833,10 +2853,47 @@ var linkedListTyped = (() => {
|
|
|
1833
2853
|
return void 0;
|
|
1834
2854
|
}
|
|
1835
2855
|
/**
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2856
|
+
* Reverse the list in place.
|
|
2857
|
+
* @remarks Time O(N), Space O(1)
|
|
2858
|
+
* @returns This list.
|
|
2859
|
+
|
|
2860
|
+
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
|
|
2864
|
+
|
|
2865
|
+
|
|
2866
|
+
|
|
2867
|
+
|
|
2868
|
+
|
|
2869
|
+
|
|
2870
|
+
|
|
2871
|
+
|
|
2872
|
+
|
|
2873
|
+
|
|
2874
|
+
|
|
2875
|
+
|
|
2876
|
+
|
|
2877
|
+
|
|
2878
|
+
|
|
2879
|
+
|
|
2880
|
+
|
|
2881
|
+
|
|
2882
|
+
|
|
2883
|
+
|
|
2884
|
+
|
|
2885
|
+
|
|
2886
|
+
|
|
2887
|
+
|
|
2888
|
+
|
|
2889
|
+
|
|
2890
|
+
|
|
2891
|
+
* @example
|
|
2892
|
+
* // Reverse in-place
|
|
2893
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2894
|
+
* list.reverse();
|
|
2895
|
+
* console.log([...list]); // [3, 2, 1];
|
|
2896
|
+
*/
|
|
1840
2897
|
reverse() {
|
|
1841
2898
|
let current = this.head;
|
|
1842
2899
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1858,22 +2915,95 @@ var linkedListTyped = (() => {
|
|
|
1858
2915
|
return this;
|
|
1859
2916
|
}
|
|
1860
2917
|
/**
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2918
|
+
* Deep clone this list (values are copied by reference).
|
|
2919
|
+
* @remarks Time O(N), Space O(N)
|
|
2920
|
+
* @returns A new list with the same element sequence.
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
|
|
2924
|
+
|
|
2925
|
+
|
|
2926
|
+
|
|
2927
|
+
|
|
2928
|
+
|
|
2929
|
+
|
|
2930
|
+
|
|
2931
|
+
|
|
2932
|
+
|
|
2933
|
+
|
|
2934
|
+
|
|
2935
|
+
|
|
2936
|
+
|
|
2937
|
+
|
|
2938
|
+
|
|
2939
|
+
|
|
2940
|
+
|
|
2941
|
+
|
|
2942
|
+
|
|
2943
|
+
|
|
2944
|
+
|
|
2945
|
+
|
|
2946
|
+
|
|
2947
|
+
|
|
2948
|
+
|
|
2949
|
+
|
|
2950
|
+
|
|
2951
|
+
* @example
|
|
2952
|
+
* // Deep copy
|
|
2953
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2954
|
+
* const copy = list.clone();
|
|
2955
|
+
* copy.pop();
|
|
2956
|
+
* console.log(list.length); // 3;
|
|
2957
|
+
*/
|
|
1865
2958
|
clone() {
|
|
1866
2959
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1867
2960
|
for (const v of this) out.push(v);
|
|
1868
2961
|
return out;
|
|
1869
2962
|
}
|
|
1870
2963
|
/**
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
2964
|
+
* Filter values into a new list of the same class.
|
|
2965
|
+
* @remarks Time O(N), Space O(N)
|
|
2966
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
2967
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2968
|
+
* @returns A new list with kept values.
|
|
2969
|
+
|
|
2970
|
+
|
|
2971
|
+
|
|
2972
|
+
|
|
2973
|
+
|
|
2974
|
+
|
|
2975
|
+
|
|
2976
|
+
|
|
2977
|
+
|
|
2978
|
+
|
|
2979
|
+
|
|
2980
|
+
|
|
2981
|
+
|
|
2982
|
+
|
|
2983
|
+
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
|
|
2987
|
+
|
|
2988
|
+
|
|
2989
|
+
|
|
2990
|
+
|
|
2991
|
+
|
|
2992
|
+
|
|
2993
|
+
|
|
2994
|
+
|
|
2995
|
+
|
|
2996
|
+
|
|
2997
|
+
|
|
2998
|
+
|
|
2999
|
+
|
|
3000
|
+
|
|
3001
|
+
* @example
|
|
3002
|
+
* // Filter elements
|
|
3003
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
3004
|
+
* const evens = list.filter(n => n % 2 === 0);
|
|
3005
|
+
* console.log([...evens]); // [2, 4];
|
|
3006
|
+
*/
|
|
1877
3007
|
filter(callback, thisArg) {
|
|
1878
3008
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1879
3009
|
let index = 0;
|
|
@@ -1897,15 +3027,61 @@ var linkedListTyped = (() => {
|
|
|
1897
3027
|
return out;
|
|
1898
3028
|
}
|
|
1899
3029
|
/**
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
3030
|
+
* Map values into a new list (possibly different element type).
|
|
3031
|
+
* @remarks Time O(N), Space O(N)
|
|
3032
|
+
* @template EM
|
|
3033
|
+
* @template RM
|
|
3034
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
3035
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
3036
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
3037
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
3038
|
+
|
|
3039
|
+
|
|
3040
|
+
|
|
3041
|
+
|
|
3042
|
+
|
|
3043
|
+
|
|
3044
|
+
|
|
3045
|
+
|
|
3046
|
+
|
|
3047
|
+
|
|
3048
|
+
|
|
3049
|
+
|
|
3050
|
+
|
|
3051
|
+
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
|
|
3055
|
+
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
|
|
3059
|
+
|
|
3060
|
+
|
|
3061
|
+
|
|
3062
|
+
|
|
3063
|
+
|
|
3064
|
+
|
|
3065
|
+
|
|
3066
|
+
|
|
3067
|
+
|
|
3068
|
+
|
|
3069
|
+
|
|
3070
|
+
* @example
|
|
3071
|
+
* // DoublyLinkedList for...of iteration and map operation
|
|
3072
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
3073
|
+
*
|
|
3074
|
+
* // Iterate through list
|
|
3075
|
+
* const doubled = list.map(value => value * 2);
|
|
3076
|
+
* console.log(doubled.length); // 5;
|
|
3077
|
+
*
|
|
3078
|
+
* // Use for...of loop
|
|
3079
|
+
* const result: number[] = [];
|
|
3080
|
+
* for (const item of list) {
|
|
3081
|
+
* result.push(item);
|
|
3082
|
+
* }
|
|
3083
|
+
* console.log(result); // [1, 2, 3, 4, 5];
|
|
3084
|
+
*/
|
|
1909
3085
|
map(callback, options, thisArg) {
|
|
1910
3086
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1911
3087
|
let index = 0;
|
|
@@ -1994,6 +3170,231 @@ var linkedListTyped = (() => {
|
|
|
1994
3170
|
}
|
|
1995
3171
|
};
|
|
1996
3172
|
|
|
3173
|
+
// src/common/error.ts
|
|
3174
|
+
var ERR = {
|
|
3175
|
+
// Range / index
|
|
3176
|
+
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
3177
|
+
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
3178
|
+
// Type / argument
|
|
3179
|
+
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
3180
|
+
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
3181
|
+
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
3182
|
+
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
3183
|
+
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
3184
|
+
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
3185
|
+
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
3186
|
+
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
3187
|
+
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
3188
|
+
// State / operation
|
|
3189
|
+
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
3190
|
+
// Matrix
|
|
3191
|
+
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
3192
|
+
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
3193
|
+
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
3194
|
+
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
3195
|
+
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
3196
|
+
};
|
|
3197
|
+
|
|
3198
|
+
// src/common/index.ts
|
|
3199
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
3200
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
3201
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
3202
|
+
return DFSOperation2;
|
|
3203
|
+
})(DFSOperation || {});
|
|
3204
|
+
var Range = class {
|
|
3205
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
3206
|
+
this.low = low;
|
|
3207
|
+
this.high = high;
|
|
3208
|
+
this.includeLow = includeLow;
|
|
3209
|
+
this.includeHigh = includeHigh;
|
|
3210
|
+
}
|
|
3211
|
+
// Determine whether a key is within the range
|
|
3212
|
+
isInRange(key, comparator) {
|
|
3213
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
3214
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
3215
|
+
return lowCheck && highCheck;
|
|
3216
|
+
}
|
|
3217
|
+
};
|
|
3218
|
+
|
|
3219
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
3220
|
+
var IterableEntryBase = class {
|
|
3221
|
+
/**
|
|
3222
|
+
* Default iterator yielding `[key, value]` entries.
|
|
3223
|
+
* @returns Iterator of `[K, V]`.
|
|
3224
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
3225
|
+
*/
|
|
3226
|
+
*[Symbol.iterator](...args) {
|
|
3227
|
+
yield* this._getIterator(...args);
|
|
3228
|
+
}
|
|
3229
|
+
/**
|
|
3230
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
3231
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
3232
|
+
* @remarks Time O(n), Space O(1)
|
|
3233
|
+
*/
|
|
3234
|
+
*entries() {
|
|
3235
|
+
for (const item of this) {
|
|
3236
|
+
yield item;
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
/**
|
|
3240
|
+
* Iterate over keys only.
|
|
3241
|
+
* @returns Iterator of keys.
|
|
3242
|
+
* @remarks Time O(n), Space O(1)
|
|
3243
|
+
*/
|
|
3244
|
+
*keys() {
|
|
3245
|
+
for (const item of this) {
|
|
3246
|
+
yield item[0];
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
/**
|
|
3250
|
+
* Iterate over values only.
|
|
3251
|
+
* @returns Iterator of values.
|
|
3252
|
+
* @remarks Time O(n), Space O(1)
|
|
3253
|
+
*/
|
|
3254
|
+
*values() {
|
|
3255
|
+
for (const item of this) {
|
|
3256
|
+
yield item[1];
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* Test whether all entries satisfy the predicate.
|
|
3261
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
3262
|
+
* @param thisArg - Optional `this` for callback.
|
|
3263
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
3264
|
+
* @remarks Time O(n), Space O(1)
|
|
3265
|
+
*/
|
|
3266
|
+
every(predicate, thisArg) {
|
|
3267
|
+
let index = 0;
|
|
3268
|
+
for (const item of this) {
|
|
3269
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
3270
|
+
return false;
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
return true;
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Test whether any entry satisfies the predicate.
|
|
3277
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
3278
|
+
* @param thisArg - Optional `this` for callback.
|
|
3279
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
3280
|
+
* @remarks Time O(n), Space O(1)
|
|
3281
|
+
*/
|
|
3282
|
+
some(predicate, thisArg) {
|
|
3283
|
+
let index = 0;
|
|
3284
|
+
for (const item of this) {
|
|
3285
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
3286
|
+
return true;
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
return false;
|
|
3290
|
+
}
|
|
3291
|
+
/**
|
|
3292
|
+
* Visit each entry, left-to-right.
|
|
3293
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
3294
|
+
* @param thisArg - Optional `this` for callback.
|
|
3295
|
+
* @remarks Time O(n), Space O(1)
|
|
3296
|
+
*/
|
|
3297
|
+
forEach(callbackfn, thisArg) {
|
|
3298
|
+
let index = 0;
|
|
3299
|
+
for (const item of this) {
|
|
3300
|
+
const [key, value] = item;
|
|
3301
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Find the first entry that matches a predicate.
|
|
3306
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
3307
|
+
* @param thisArg - Optional `this` for callback.
|
|
3308
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
3309
|
+
* @remarks Time O(n), Space O(1)
|
|
3310
|
+
*/
|
|
3311
|
+
find(callbackfn, thisArg) {
|
|
3312
|
+
let index = 0;
|
|
3313
|
+
for (const item of this) {
|
|
3314
|
+
const [key, value] = item;
|
|
3315
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
3316
|
+
}
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3319
|
+
/**
|
|
3320
|
+
* Whether the given key exists.
|
|
3321
|
+
* @param key - Key to test.
|
|
3322
|
+
* @returns `true` if found; otherwise `false`.
|
|
3323
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
3324
|
+
*/
|
|
3325
|
+
has(key) {
|
|
3326
|
+
for (const item of this) {
|
|
3327
|
+
const [itemKey] = item;
|
|
3328
|
+
if (itemKey === key) return true;
|
|
3329
|
+
}
|
|
3330
|
+
return false;
|
|
3331
|
+
}
|
|
3332
|
+
/**
|
|
3333
|
+
* Whether there exists an entry with the given value.
|
|
3334
|
+
* @param value - Value to test.
|
|
3335
|
+
* @returns `true` if found; otherwise `false`.
|
|
3336
|
+
* @remarks Time O(n), Space O(1)
|
|
3337
|
+
*/
|
|
3338
|
+
hasValue(value) {
|
|
3339
|
+
for (const [, elementValue] of this) {
|
|
3340
|
+
if (elementValue === value) return true;
|
|
3341
|
+
}
|
|
3342
|
+
return false;
|
|
3343
|
+
}
|
|
3344
|
+
/**
|
|
3345
|
+
* Get the value under a key.
|
|
3346
|
+
* @param key - Key to look up.
|
|
3347
|
+
* @returns Value or `undefined`.
|
|
3348
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
3349
|
+
*/
|
|
3350
|
+
get(key) {
|
|
3351
|
+
for (const item of this) {
|
|
3352
|
+
const [itemKey, value] = item;
|
|
3353
|
+
if (itemKey === key) return value;
|
|
3354
|
+
}
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
/**
|
|
3358
|
+
* Reduce entries into a single accumulator.
|
|
3359
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
3360
|
+
* @param initialValue - Initial accumulator.
|
|
3361
|
+
* @returns Final accumulator.
|
|
3362
|
+
* @remarks Time O(n), Space O(1)
|
|
3363
|
+
*/
|
|
3364
|
+
reduce(callbackfn, initialValue) {
|
|
3365
|
+
let accumulator = initialValue;
|
|
3366
|
+
let index = 0;
|
|
3367
|
+
for (const item of this) {
|
|
3368
|
+
const [key, value] = item;
|
|
3369
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
3370
|
+
}
|
|
3371
|
+
return accumulator;
|
|
3372
|
+
}
|
|
3373
|
+
/**
|
|
3374
|
+
* Converts data structure to `[key, value]` pairs.
|
|
3375
|
+
* @returns Array of entries.
|
|
3376
|
+
* @remarks Time O(n), Space O(n)
|
|
3377
|
+
*/
|
|
3378
|
+
toArray() {
|
|
3379
|
+
return [...this];
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
3383
|
+
* @returns Array of entries (default) or a string.
|
|
3384
|
+
* @remarks Time O(n), Space O(n)
|
|
3385
|
+
*/
|
|
3386
|
+
toVisual() {
|
|
3387
|
+
return [...this];
|
|
3388
|
+
}
|
|
3389
|
+
/**
|
|
3390
|
+
* Print a human-friendly representation to the console.
|
|
3391
|
+
* @remarks Time O(n), Space O(n)
|
|
3392
|
+
*/
|
|
3393
|
+
print() {
|
|
3394
|
+
console.log(this.toVisual());
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
|
|
1997
3398
|
// src/data-structures/linked-list/skip-linked-list.ts
|
|
1998
3399
|
var SkipListNode = class {
|
|
1999
3400
|
constructor(key, value, level) {
|
|
@@ -2002,29 +3403,67 @@ var linkedListTyped = (() => {
|
|
|
2002
3403
|
__publicField(this, "forward");
|
|
2003
3404
|
this.key = key;
|
|
2004
3405
|
this.value = value;
|
|
2005
|
-
this.forward = new Array(level);
|
|
3406
|
+
this.forward = new Array(level).fill(void 0);
|
|
2006
3407
|
}
|
|
2007
3408
|
};
|
|
2008
|
-
var
|
|
2009
|
-
|
|
2010
|
-
|
|
3409
|
+
var _comparator, _isDefaultComparator;
|
|
3410
|
+
var _SkipList = class _SkipList extends IterableEntryBase {
|
|
3411
|
+
constructor(entries = [], options = {}) {
|
|
3412
|
+
super();
|
|
3413
|
+
__privateAdd(this, _comparator);
|
|
3414
|
+
__privateAdd(this, _isDefaultComparator);
|
|
3415
|
+
// ─── Internal state ──────────────────────────────────────────
|
|
3416
|
+
__publicField(this, "_head");
|
|
2011
3417
|
__publicField(this, "_level", 0);
|
|
3418
|
+
__publicField(this, "_size", 0);
|
|
2012
3419
|
__publicField(this, "_maxLevel", 16);
|
|
2013
3420
|
__publicField(this, "_probability", 0.5);
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
3421
|
+
const { comparator, toEntryFn, maxLevel, probability } = options;
|
|
3422
|
+
if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
|
|
3423
|
+
if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
|
|
3424
|
+
__privateSet(this, _isDefaultComparator, comparator === void 0);
|
|
3425
|
+
__privateSet(this, _comparator, comparator != null ? comparator : _SkipList.createDefaultComparator());
|
|
3426
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
3427
|
+
for (const item of entries) {
|
|
3428
|
+
let k;
|
|
3429
|
+
let v;
|
|
3430
|
+
if (toEntryFn) {
|
|
3431
|
+
[k, v] = toEntryFn(item);
|
|
3432
|
+
} else {
|
|
3433
|
+
if (!Array.isArray(item) || item.length < 2) {
|
|
3434
|
+
throw new TypeError(ERR.invalidEntry("SkipList"));
|
|
3435
|
+
}
|
|
3436
|
+
[k, v] = item;
|
|
3437
|
+
}
|
|
3438
|
+
this.set(k, v);
|
|
2021
3439
|
}
|
|
2022
3440
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
3441
|
+
/**
|
|
3442
|
+
* Creates a default comparator supporting number, string, Date, and bigint.
|
|
3443
|
+
*/
|
|
3444
|
+
static createDefaultComparator() {
|
|
3445
|
+
return (a, b) => {
|
|
3446
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
3447
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
|
|
3448
|
+
return a - b;
|
|
3449
|
+
}
|
|
3450
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
3451
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3452
|
+
}
|
|
3453
|
+
if (a instanceof Date && b instanceof Date) {
|
|
3454
|
+
const ta = a.getTime(), tb = b.getTime();
|
|
3455
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
|
|
3456
|
+
return ta - tb;
|
|
3457
|
+
}
|
|
3458
|
+
if (typeof a === "bigint" && typeof b === "bigint") {
|
|
3459
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3460
|
+
}
|
|
3461
|
+
throw new TypeError(ERR.comparatorRequired("SkipList"));
|
|
3462
|
+
};
|
|
2025
3463
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
3464
|
+
// ─── Size & lifecycle ────────────────────────────────────────
|
|
3465
|
+
get size() {
|
|
3466
|
+
return this._size;
|
|
2028
3467
|
}
|
|
2029
3468
|
get maxLevel() {
|
|
2030
3469
|
return this._maxLevel;
|
|
@@ -2032,108 +3471,971 @@ var linkedListTyped = (() => {
|
|
|
2032
3471
|
get probability() {
|
|
2033
3472
|
return this._probability;
|
|
2034
3473
|
}
|
|
2035
|
-
get
|
|
2036
|
-
|
|
2037
|
-
return firstNode ? firstNode.value : void 0;
|
|
3474
|
+
get comparator() {
|
|
3475
|
+
return __privateGet(this, _comparator);
|
|
2038
3476
|
}
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
3477
|
+
/**
|
|
3478
|
+
* Check if empty
|
|
3479
|
+
|
|
3480
|
+
|
|
3481
|
+
|
|
3482
|
+
|
|
3483
|
+
|
|
3484
|
+
|
|
3485
|
+
|
|
3486
|
+
|
|
3487
|
+
|
|
3488
|
+
|
|
3489
|
+
|
|
3490
|
+
|
|
3491
|
+
|
|
3492
|
+
|
|
3493
|
+
|
|
3494
|
+
|
|
3495
|
+
|
|
3496
|
+
|
|
3497
|
+
|
|
3498
|
+
|
|
3499
|
+
|
|
3500
|
+
|
|
3501
|
+
|
|
3502
|
+
|
|
3503
|
+
|
|
3504
|
+
|
|
3505
|
+
|
|
3506
|
+
|
|
3507
|
+
|
|
3508
|
+
* @example
|
|
3509
|
+
* // Check if empty
|
|
3510
|
+
* const sl = new SkipList<number, string>();
|
|
3511
|
+
* console.log(sl.isEmpty()); // true;
|
|
3512
|
+
*/
|
|
3513
|
+
isEmpty() {
|
|
3514
|
+
return this._size === 0;
|
|
2047
3515
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
3516
|
+
/**
|
|
3517
|
+
* Remove all entries
|
|
3518
|
+
|
|
3519
|
+
|
|
3520
|
+
|
|
3521
|
+
|
|
3522
|
+
|
|
3523
|
+
|
|
3524
|
+
|
|
3525
|
+
|
|
3526
|
+
|
|
3527
|
+
|
|
3528
|
+
|
|
3529
|
+
|
|
3530
|
+
|
|
3531
|
+
|
|
3532
|
+
|
|
3533
|
+
|
|
3534
|
+
|
|
3535
|
+
|
|
3536
|
+
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
* @example
|
|
3548
|
+
* // Remove all entries
|
|
3549
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3550
|
+
* sl.clear();
|
|
3551
|
+
* console.log(sl.isEmpty()); // true;
|
|
3552
|
+
*/
|
|
3553
|
+
clear() {
|
|
3554
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
3555
|
+
this._level = 0;
|
|
3556
|
+
this._size = 0;
|
|
3557
|
+
}
|
|
3558
|
+
/**
|
|
3559
|
+
* Create independent copy
|
|
3560
|
+
|
|
3561
|
+
|
|
3562
|
+
|
|
3563
|
+
|
|
3564
|
+
|
|
3565
|
+
|
|
3566
|
+
|
|
3567
|
+
|
|
3568
|
+
|
|
3569
|
+
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
|
|
3573
|
+
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
|
|
3577
|
+
|
|
3578
|
+
|
|
3579
|
+
|
|
3580
|
+
|
|
3581
|
+
|
|
3582
|
+
|
|
3583
|
+
|
|
3584
|
+
|
|
3585
|
+
|
|
3586
|
+
|
|
3587
|
+
|
|
3588
|
+
|
|
3589
|
+
* @example
|
|
3590
|
+
* // Create independent copy
|
|
3591
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3592
|
+
* const copy = sl.clone();
|
|
3593
|
+
* copy.delete(1);
|
|
3594
|
+
* console.log(sl.has(1)); // true;
|
|
3595
|
+
*/
|
|
3596
|
+
clone() {
|
|
3597
|
+
return new _SkipList(this, {
|
|
3598
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
3599
|
+
maxLevel: this._maxLevel,
|
|
3600
|
+
probability: this._probability
|
|
3601
|
+
});
|
|
3602
|
+
}
|
|
3603
|
+
// ─── Core CRUD ───────────────────────────────────────────────
|
|
3604
|
+
/**
|
|
3605
|
+
* Insert or update a key-value pair. Returns `this` for chaining.
|
|
3606
|
+
* Unique keys only — if key exists, value is updated in place.
|
|
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
|
+
|
|
3634
|
+
|
|
3635
|
+
|
|
3636
|
+
|
|
3637
|
+
|
|
3638
|
+
|
|
3639
|
+
* @example
|
|
3640
|
+
* // In-memory sorted key-value store
|
|
3641
|
+
* const store = new SkipList<number, string>();
|
|
3642
|
+
*
|
|
3643
|
+
* store.set(3, 'three');
|
|
3644
|
+
* store.set(1, 'one');
|
|
3645
|
+
* store.set(5, 'five');
|
|
3646
|
+
* store.set(2, 'two');
|
|
3647
|
+
*
|
|
3648
|
+
* console.log(store.get(3)); // 'three';
|
|
3649
|
+
* console.log(store.get(1)); // 'one';
|
|
3650
|
+
* console.log(store.get(5)); // 'five';
|
|
3651
|
+
*
|
|
3652
|
+
* // Update existing key
|
|
3653
|
+
* store.set(3, 'THREE');
|
|
3654
|
+
* console.log(store.get(3)); // 'THREE';
|
|
3655
|
+
*/
|
|
3656
|
+
set(key, value) {
|
|
3657
|
+
const cmp = __privateGet(this, _comparator);
|
|
3658
|
+
const update = this._findUpdate(key);
|
|
3659
|
+
const existing = update[0].forward[0];
|
|
3660
|
+
if (existing && cmp(existing.key, key) === 0) {
|
|
3661
|
+
existing.value = value;
|
|
3662
|
+
return this;
|
|
3663
|
+
}
|
|
3664
|
+
const newLevel = this._randomLevel();
|
|
3665
|
+
const newNode = new SkipListNode(key, value, newLevel);
|
|
3666
|
+
if (newLevel > this._level) {
|
|
3667
|
+
for (let i = this._level; i < newLevel; i++) {
|
|
3668
|
+
update[i] = this._head;
|
|
2055
3669
|
}
|
|
2056
|
-
|
|
3670
|
+
this._level = newLevel;
|
|
2057
3671
|
}
|
|
2058
|
-
for (let i = 0; i <
|
|
3672
|
+
for (let i = 0; i < newLevel; i++) {
|
|
2059
3673
|
newNode.forward[i] = update[i].forward[i];
|
|
2060
3674
|
update[i].forward[i] = newNode;
|
|
2061
3675
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
}
|
|
3676
|
+
this._size++;
|
|
3677
|
+
return this;
|
|
2065
3678
|
}
|
|
3679
|
+
/**
|
|
3680
|
+
* Get the value for a key, or `undefined` if not found.
|
|
3681
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
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
|
+
|
|
3709
|
+
|
|
3710
|
+
|
|
3711
|
+
|
|
3712
|
+
|
|
3713
|
+
|
|
3714
|
+
* @example
|
|
3715
|
+
* // Building a sorted index
|
|
3716
|
+
* type Product = { id: number; name: string; price: number };
|
|
3717
|
+
* const products: Product[] = [
|
|
3718
|
+
* { id: 1, name: 'Widget', price: 25 },
|
|
3719
|
+
* { id: 2, name: 'Gadget', price: 50 },
|
|
3720
|
+
* { id: 3, name: 'Doohickey', price: 15 }
|
|
3721
|
+
* ];
|
|
3722
|
+
*
|
|
3723
|
+
* const index = new SkipList<number, Product, Product>(products, {
|
|
3724
|
+
* toEntryFn: (p: Product) => [p.price, p]
|
|
3725
|
+
* });
|
|
3726
|
+
*
|
|
3727
|
+
* // Iterate in sorted order by price
|
|
3728
|
+
* const names = [...index.values()].map(p => p!.name);
|
|
3729
|
+
* console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
|
|
3730
|
+
*
|
|
3731
|
+
* // Range search: products between $20 and $60
|
|
3732
|
+
* const range = index.rangeSearch([20, 60]);
|
|
3733
|
+
* console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
|
|
3734
|
+
*/
|
|
2066
3735
|
get(key) {
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
while (current.forward[i] && current.forward[i].key < key) {
|
|
2070
|
-
current = current.forward[i];
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
current = current.forward[0];
|
|
2074
|
-
if (current && current.key === key) {
|
|
2075
|
-
return current.value;
|
|
2076
|
-
}
|
|
2077
|
-
return void 0;
|
|
3736
|
+
const node = this._findNode(key);
|
|
3737
|
+
return node ? node.value : void 0;
|
|
2078
3738
|
}
|
|
3739
|
+
/**
|
|
3740
|
+
* Check if a key exists.
|
|
3741
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
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
|
+
|
|
3769
|
+
|
|
3770
|
+
|
|
3771
|
+
|
|
3772
|
+
|
|
3773
|
+
|
|
3774
|
+
* @example
|
|
3775
|
+
* // Check key existence
|
|
3776
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
|
|
3777
|
+
* console.log(sl.has(3)); // true;
|
|
3778
|
+
* console.log(sl.has(4)); // false;
|
|
3779
|
+
*/
|
|
2079
3780
|
has(key) {
|
|
2080
|
-
return this.
|
|
3781
|
+
return this._findNode(key) !== void 0;
|
|
2081
3782
|
}
|
|
3783
|
+
/**
|
|
3784
|
+
* Delete a key. Returns `true` if the key was found and removed.
|
|
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
|
+
|
|
3812
|
+
|
|
3813
|
+
|
|
3814
|
+
|
|
3815
|
+
|
|
3816
|
+
|
|
3817
|
+
* @example
|
|
3818
|
+
* // Fast lookup with deletion
|
|
3819
|
+
* const cache = new SkipList<string, number>();
|
|
3820
|
+
*
|
|
3821
|
+
* cache.set('alpha', 1);
|
|
3822
|
+
* cache.set('beta', 2);
|
|
3823
|
+
* cache.set('gamma', 3);
|
|
3824
|
+
*
|
|
3825
|
+
* console.log(cache.has('beta')); // true;
|
|
3826
|
+
* cache.delete('beta');
|
|
3827
|
+
* console.log(cache.has('beta')); // false;
|
|
3828
|
+
* console.log(cache.size); // 2;
|
|
3829
|
+
*/
|
|
2082
3830
|
delete(key) {
|
|
2083
|
-
const
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
3831
|
+
const cmp = __privateGet(this, _comparator);
|
|
3832
|
+
const update = this._findUpdate(key);
|
|
3833
|
+
const target = update[0].forward[0];
|
|
3834
|
+
if (!target || cmp(target.key, key) !== 0) return false;
|
|
3835
|
+
for (let i = 0; i < this._level; i++) {
|
|
3836
|
+
if (update[i].forward[i] !== target) break;
|
|
3837
|
+
update[i].forward[i] = target.forward[i];
|
|
3838
|
+
}
|
|
3839
|
+
while (this._level > 0 && !this._head.forward[this._level - 1]) {
|
|
3840
|
+
this._level--;
|
|
3841
|
+
}
|
|
3842
|
+
this._size--;
|
|
3843
|
+
return true;
|
|
3844
|
+
}
|
|
3845
|
+
// ─── Navigation ──────────────────────────────────────────────
|
|
3846
|
+
/**
|
|
3847
|
+
* Returns the first (smallest key) entry, or `undefined` if empty.
|
|
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
|
+
|
|
3875
|
+
|
|
3876
|
+
|
|
3877
|
+
|
|
3878
|
+
|
|
3879
|
+
|
|
3880
|
+
* @example
|
|
3881
|
+
* // Access the minimum entry
|
|
3882
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3883
|
+
* console.log(sl.first()); // [1, 'a'];
|
|
3884
|
+
*/
|
|
3885
|
+
first() {
|
|
3886
|
+
const node = this._head.forward[0];
|
|
3887
|
+
return node ? [node.key, node.value] : void 0;
|
|
3888
|
+
}
|
|
3889
|
+
/**
|
|
3890
|
+
* Returns the last (largest key) entry, or `undefined` if empty.
|
|
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
|
+
|
|
3918
|
+
|
|
3919
|
+
|
|
3920
|
+
|
|
3921
|
+
|
|
3922
|
+
|
|
3923
|
+
* @example
|
|
3924
|
+
* // Access the maximum entry
|
|
3925
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3926
|
+
* console.log(sl.last()); // [5, 'e'];
|
|
3927
|
+
*/
|
|
3928
|
+
last() {
|
|
3929
|
+
let current = this._head;
|
|
3930
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3931
|
+
while (current.forward[i]) {
|
|
2087
3932
|
current = current.forward[i];
|
|
2088
3933
|
}
|
|
2089
|
-
update[i] = current;
|
|
2090
3934
|
}
|
|
2091
|
-
current
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
3935
|
+
return current === this._head ? void 0 : [current.key, current.value];
|
|
3936
|
+
}
|
|
3937
|
+
/**
|
|
3938
|
+
* Remove and return the first (smallest key) entry.
|
|
3939
|
+
|
|
3940
|
+
|
|
3941
|
+
|
|
3942
|
+
|
|
3943
|
+
|
|
3944
|
+
|
|
3945
|
+
|
|
3946
|
+
|
|
3947
|
+
|
|
3948
|
+
|
|
3949
|
+
|
|
3950
|
+
|
|
3951
|
+
|
|
3952
|
+
|
|
3953
|
+
|
|
3954
|
+
|
|
3955
|
+
|
|
3956
|
+
|
|
3957
|
+
|
|
3958
|
+
|
|
3959
|
+
|
|
3960
|
+
|
|
3961
|
+
|
|
3962
|
+
|
|
3963
|
+
|
|
3964
|
+
|
|
3965
|
+
|
|
3966
|
+
|
|
3967
|
+
|
|
3968
|
+
* @example
|
|
3969
|
+
* // Remove and return smallest
|
|
3970
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3971
|
+
* console.log(sl.pollFirst()); // [1, 'a'];
|
|
3972
|
+
* console.log(sl.size); // 2;
|
|
3973
|
+
*/
|
|
3974
|
+
pollFirst() {
|
|
3975
|
+
const entry = this.first();
|
|
3976
|
+
if (!entry) return void 0;
|
|
3977
|
+
this.delete(entry[0]);
|
|
3978
|
+
return entry;
|
|
3979
|
+
}
|
|
3980
|
+
/**
|
|
3981
|
+
* Remove and return the last (largest key) entry.
|
|
3982
|
+
|
|
3983
|
+
|
|
3984
|
+
|
|
3985
|
+
|
|
3986
|
+
|
|
3987
|
+
|
|
3988
|
+
|
|
3989
|
+
|
|
3990
|
+
|
|
3991
|
+
|
|
3992
|
+
|
|
3993
|
+
|
|
3994
|
+
|
|
3995
|
+
|
|
3996
|
+
|
|
3997
|
+
|
|
3998
|
+
|
|
3999
|
+
|
|
4000
|
+
|
|
4001
|
+
|
|
4002
|
+
|
|
4003
|
+
|
|
4004
|
+
|
|
4005
|
+
|
|
4006
|
+
|
|
4007
|
+
|
|
4008
|
+
|
|
4009
|
+
|
|
4010
|
+
|
|
4011
|
+
* @example
|
|
4012
|
+
* // Remove and return largest
|
|
4013
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
4014
|
+
* console.log(sl.pollLast()); // [3, 'c'];
|
|
4015
|
+
* console.log(sl.size); // 2;
|
|
4016
|
+
*/
|
|
4017
|
+
pollLast() {
|
|
4018
|
+
const entry = this.last();
|
|
4019
|
+
if (!entry) return void 0;
|
|
4020
|
+
this.delete(entry[0]);
|
|
4021
|
+
return entry;
|
|
4022
|
+
}
|
|
4023
|
+
/**
|
|
4024
|
+
* Least entry ≥ key, or `undefined`.
|
|
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
|
+
|
|
4052
|
+
|
|
4053
|
+
|
|
4054
|
+
|
|
4055
|
+
|
|
4056
|
+
|
|
4057
|
+
* @example
|
|
4058
|
+
* // Least entry ≥ key
|
|
4059
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4060
|
+
* console.log(sl.ceiling(15)); // [20, 'b'];
|
|
4061
|
+
* console.log(sl.ceiling(20)); // [20, 'b'];
|
|
4062
|
+
*/
|
|
4063
|
+
ceiling(key) {
|
|
4064
|
+
const cmp = __privateGet(this, _comparator);
|
|
4065
|
+
let current = this._head;
|
|
4066
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4067
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4068
|
+
current = current.forward[i];
|
|
2098
4069
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
4070
|
+
}
|
|
4071
|
+
const node = current.forward[0];
|
|
4072
|
+
return node ? [node.key, node.value] : void 0;
|
|
4073
|
+
}
|
|
4074
|
+
/**
|
|
4075
|
+
* Greatest entry ≤ key, or `undefined`.
|
|
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
|
+
|
|
4103
|
+
|
|
4104
|
+
|
|
4105
|
+
|
|
4106
|
+
|
|
4107
|
+
|
|
4108
|
+
* @example
|
|
4109
|
+
* // Greatest entry ≤ key
|
|
4110
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4111
|
+
* console.log(sl.floor(25)); // [20, 'b'];
|
|
4112
|
+
* console.log(sl.floor(5)); // undefined;
|
|
4113
|
+
*/
|
|
4114
|
+
floor(key) {
|
|
4115
|
+
const cmp = __privateGet(this, _comparator);
|
|
4116
|
+
let current = this._head;
|
|
4117
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4118
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
4119
|
+
current = current.forward[i];
|
|
2101
4120
|
}
|
|
2102
|
-
return true;
|
|
2103
4121
|
}
|
|
2104
|
-
|
|
4122
|
+
const result = current === this._head ? void 0 : current;
|
|
4123
|
+
if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
|
|
4124
|
+
return void 0;
|
|
2105
4125
|
}
|
|
4126
|
+
/**
|
|
4127
|
+
* Least entry strictly > key, or `undefined`.
|
|
4128
|
+
|
|
4129
|
+
|
|
4130
|
+
|
|
4131
|
+
|
|
4132
|
+
|
|
4133
|
+
|
|
4134
|
+
|
|
4135
|
+
|
|
4136
|
+
|
|
4137
|
+
|
|
4138
|
+
|
|
4139
|
+
|
|
4140
|
+
|
|
4141
|
+
|
|
4142
|
+
|
|
4143
|
+
|
|
4144
|
+
|
|
4145
|
+
|
|
4146
|
+
|
|
4147
|
+
|
|
4148
|
+
|
|
4149
|
+
|
|
4150
|
+
|
|
4151
|
+
|
|
4152
|
+
|
|
4153
|
+
|
|
4154
|
+
|
|
4155
|
+
|
|
4156
|
+
|
|
4157
|
+
* @example
|
|
4158
|
+
* // Strictly greater entry
|
|
4159
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4160
|
+
* console.log(sl.higher(15)); // [20, 'b'];
|
|
4161
|
+
* console.log(sl.higher(30)); // undefined;
|
|
4162
|
+
*/
|
|
2106
4163
|
higher(key) {
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
4164
|
+
const cmp = __privateGet(this, _comparator);
|
|
4165
|
+
let current = this._head;
|
|
4166
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4167
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
2110
4168
|
current = current.forward[i];
|
|
2111
4169
|
}
|
|
2112
4170
|
}
|
|
2113
|
-
const
|
|
2114
|
-
return
|
|
4171
|
+
const node = current.forward[0];
|
|
4172
|
+
return node ? [node.key, node.value] : void 0;
|
|
2115
4173
|
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Greatest entry strictly < key, or `undefined`.
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
|
|
4192
|
+
|
|
4193
|
+
|
|
4194
|
+
|
|
4195
|
+
|
|
4196
|
+
|
|
4197
|
+
|
|
4198
|
+
|
|
4199
|
+
|
|
4200
|
+
|
|
4201
|
+
|
|
4202
|
+
|
|
4203
|
+
|
|
4204
|
+
|
|
4205
|
+
* @example
|
|
4206
|
+
* // Strictly less entry
|
|
4207
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
4208
|
+
* console.log(sl.lower(25)); // [20, 'b'];
|
|
4209
|
+
* console.log(sl.lower(10)); // undefined;
|
|
4210
|
+
*/
|
|
2116
4211
|
lower(key) {
|
|
2117
|
-
|
|
2118
|
-
let
|
|
2119
|
-
|
|
2120
|
-
|
|
4212
|
+
const cmp = __privateGet(this, _comparator);
|
|
4213
|
+
let current = this._head;
|
|
4214
|
+
let result;
|
|
4215
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4216
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2121
4217
|
current = current.forward[i];
|
|
2122
4218
|
}
|
|
2123
|
-
if (current.key <
|
|
2124
|
-
|
|
4219
|
+
if (current !== this._head && cmp(current.key, key) < 0) {
|
|
4220
|
+
result = current;
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
return result ? [result.key, result.value] : void 0;
|
|
4224
|
+
}
|
|
4225
|
+
/**
|
|
4226
|
+
* Returns entries within the given key range.
|
|
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
|
+
|
|
4254
|
+
|
|
4255
|
+
|
|
4256
|
+
|
|
4257
|
+
|
|
4258
|
+
|
|
4259
|
+
* @example
|
|
4260
|
+
* // Find entries in a range
|
|
4261
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
|
|
4262
|
+
* const result = sl.rangeSearch([2, 4]);
|
|
4263
|
+
* console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
4264
|
+
*/
|
|
4265
|
+
rangeSearch(range, options = {}) {
|
|
4266
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
4267
|
+
const [low, high] = range;
|
|
4268
|
+
const cmp = __privateGet(this, _comparator);
|
|
4269
|
+
const out = [];
|
|
4270
|
+
let current = this._head;
|
|
4271
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4272
|
+
while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
|
|
4273
|
+
current = current.forward[i];
|
|
2125
4274
|
}
|
|
2126
4275
|
}
|
|
2127
|
-
|
|
4276
|
+
current = current.forward[0];
|
|
4277
|
+
while (current) {
|
|
4278
|
+
const cmpHigh = cmp(current.key, high);
|
|
4279
|
+
if (cmpHigh > 0) break;
|
|
4280
|
+
if (cmpHigh === 0 && !highInclusive) break;
|
|
4281
|
+
const cmpLow = cmp(current.key, low);
|
|
4282
|
+
if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
|
|
4283
|
+
out.push([current.key, current.value]);
|
|
4284
|
+
}
|
|
4285
|
+
current = current.forward[0];
|
|
4286
|
+
}
|
|
4287
|
+
return out;
|
|
4288
|
+
}
|
|
4289
|
+
// ─── Functional (overrides) ──────────────────────────────────
|
|
4290
|
+
/**
|
|
4291
|
+
* Creates a new SkipList with entries transformed by callback.
|
|
4292
|
+
|
|
4293
|
+
|
|
4294
|
+
|
|
4295
|
+
|
|
4296
|
+
|
|
4297
|
+
|
|
4298
|
+
|
|
4299
|
+
|
|
4300
|
+
|
|
4301
|
+
|
|
4302
|
+
|
|
4303
|
+
|
|
4304
|
+
|
|
4305
|
+
|
|
4306
|
+
|
|
4307
|
+
|
|
4308
|
+
|
|
4309
|
+
|
|
4310
|
+
|
|
4311
|
+
|
|
4312
|
+
|
|
4313
|
+
|
|
4314
|
+
|
|
4315
|
+
|
|
4316
|
+
|
|
4317
|
+
|
|
4318
|
+
|
|
4319
|
+
|
|
4320
|
+
|
|
4321
|
+
* @example
|
|
4322
|
+
* // Transform entries
|
|
4323
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
4324
|
+
* const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
|
|
4325
|
+
* console.log([...mapped.values()]); // ['A', 'B'];
|
|
4326
|
+
*/
|
|
4327
|
+
map(callback, options) {
|
|
4328
|
+
const out = new _SkipList([], options != null ? options : {});
|
|
4329
|
+
let i = 0;
|
|
4330
|
+
for (const [k, v] of this) {
|
|
4331
|
+
const [nk, nv] = callback(v, k, i++, this);
|
|
4332
|
+
out.set(nk, nv);
|
|
4333
|
+
}
|
|
4334
|
+
return out;
|
|
4335
|
+
}
|
|
4336
|
+
/**
|
|
4337
|
+
* Creates a new SkipList with entries that pass the predicate.
|
|
4338
|
+
|
|
4339
|
+
|
|
4340
|
+
|
|
4341
|
+
|
|
4342
|
+
|
|
4343
|
+
|
|
4344
|
+
|
|
4345
|
+
|
|
4346
|
+
|
|
4347
|
+
|
|
4348
|
+
|
|
4349
|
+
|
|
4350
|
+
|
|
4351
|
+
|
|
4352
|
+
|
|
4353
|
+
|
|
4354
|
+
|
|
4355
|
+
|
|
4356
|
+
|
|
4357
|
+
|
|
4358
|
+
|
|
4359
|
+
|
|
4360
|
+
|
|
4361
|
+
|
|
4362
|
+
|
|
4363
|
+
|
|
4364
|
+
|
|
4365
|
+
|
|
4366
|
+
|
|
4367
|
+
* @example
|
|
4368
|
+
* // Filter entries
|
|
4369
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
4370
|
+
* const result = sl.filter((v, k) => k > 1);
|
|
4371
|
+
* console.log(result.size); // 2;
|
|
4372
|
+
*/
|
|
4373
|
+
filter(callbackfn, thisArg) {
|
|
4374
|
+
const out = new _SkipList([], {
|
|
4375
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
4376
|
+
maxLevel: this._maxLevel,
|
|
4377
|
+
probability: this._probability
|
|
4378
|
+
});
|
|
4379
|
+
let i = 0;
|
|
4380
|
+
for (const [k, v] of this) {
|
|
4381
|
+
const ok = callbackfn.call(thisArg, v, k, i++, this);
|
|
4382
|
+
if (ok) out.set(k, v);
|
|
4383
|
+
}
|
|
4384
|
+
return out;
|
|
4385
|
+
}
|
|
4386
|
+
// ─── Iterator (required by IterableEntryBase) ────────────────
|
|
4387
|
+
_getIterator() {
|
|
4388
|
+
const head = this._head;
|
|
4389
|
+
return (function* () {
|
|
4390
|
+
let node = head.forward[0];
|
|
4391
|
+
while (node) {
|
|
4392
|
+
yield [node.key, node.value];
|
|
4393
|
+
node = node.forward[0];
|
|
4394
|
+
}
|
|
4395
|
+
})();
|
|
4396
|
+
}
|
|
4397
|
+
// ─── Internal helpers ────────────────────────────────────────
|
|
4398
|
+
/**
|
|
4399
|
+
* Finds the update array (predecessors at each level) for a given key.
|
|
4400
|
+
*/
|
|
4401
|
+
_findUpdate(key) {
|
|
4402
|
+
const cmp = __privateGet(this, _comparator);
|
|
4403
|
+
const update = new Array(this._maxLevel).fill(this._head);
|
|
4404
|
+
let current = this._head;
|
|
4405
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4406
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4407
|
+
current = current.forward[i];
|
|
4408
|
+
}
|
|
4409
|
+
update[i] = current;
|
|
4410
|
+
}
|
|
4411
|
+
return update;
|
|
4412
|
+
}
|
|
4413
|
+
/**
|
|
4414
|
+
* Finds the node for a given key, or undefined.
|
|
4415
|
+
*/
|
|
4416
|
+
_findNode(key) {
|
|
4417
|
+
const cmp = __privateGet(this, _comparator);
|
|
4418
|
+
let current = this._head;
|
|
4419
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
4420
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
4421
|
+
current = current.forward[i];
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
const candidate = current.forward[0];
|
|
4425
|
+
if (candidate && cmp(candidate.key, key) === 0) return candidate;
|
|
4426
|
+
return void 0;
|
|
2128
4427
|
}
|
|
2129
4428
|
_randomLevel() {
|
|
2130
4429
|
let level = 1;
|
|
2131
|
-
while (Math.random() < this.
|
|
4430
|
+
while (Math.random() < this._probability && level < this._maxLevel) {
|
|
2132
4431
|
level++;
|
|
2133
4432
|
}
|
|
2134
4433
|
return level;
|
|
2135
4434
|
}
|
|
2136
4435
|
};
|
|
4436
|
+
_comparator = new WeakMap();
|
|
4437
|
+
_isDefaultComparator = new WeakMap();
|
|
4438
|
+
var SkipList = _SkipList;
|
|
2137
4439
|
return __toCommonJS(src_exports);
|
|
2138
4440
|
})();
|
|
2139
4441
|
/**
|