linked-list-typed 2.4.5 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -50
- package/dist/cjs/index.cjs +1538 -294
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1544 -291
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1538 -294
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1544 -291
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +429 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +212 -32
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/directed-graph.d.ts +219 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +272 -65
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/umd/linked-list-typed.js +1541 -289
- package/dist/umd/linked-list-typed.js.map +1 -1
- package/dist/umd/linked-list-typed.min.js +1 -1
- package/dist/umd/linked-list-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
- package/src/data-structures/binary-tree/binary-tree.ts +429 -79
- package/src/data-structures/binary-tree/bst.ts +335 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1284 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
- package/src/data-structures/binary-tree/tree-set.ts +1136 -9
- package/src/data-structures/graph/directed-graph.ts +219 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +204 -59
- package/src/data-structures/hash/hash-map.ts +230 -77
- package/src/data-structures/heap/heap.ts +287 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +416 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +272 -65
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +213 -43
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
|
@@ -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,37 @@ 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
|
+
* @example
|
|
766
|
+
* // basic SinglyLinkedList creation and push operation
|
|
767
|
+
* // Create a simple SinglyLinkedList with initial values
|
|
768
|
+
* const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
|
769
|
+
*
|
|
770
|
+
* // Verify the list maintains insertion order
|
|
771
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
772
|
+
*
|
|
773
|
+
* // Check length
|
|
774
|
+
* console.log(list.length); // 5;
|
|
775
|
+
*
|
|
776
|
+
* // Push a new element to the end
|
|
777
|
+
* list.push(6);
|
|
778
|
+
* console.log(list.length); // 6;
|
|
779
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
780
|
+
*/
|
|
794
781
|
push(elementOrNode) {
|
|
795
782
|
const newNode = this._ensureNode(elementOrNode);
|
|
796
783
|
if (!this.head) {
|
|
@@ -804,10 +791,36 @@ var linkedListTyped = (() => {
|
|
|
804
791
|
return true;
|
|
805
792
|
}
|
|
806
793
|
/**
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
794
|
+
* Remove and return the tail element.
|
|
795
|
+
* @remarks Time O(N), Space O(1)
|
|
796
|
+
* @returns Removed element or undefined.
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
* @example
|
|
809
|
+
* // SinglyLinkedList pop and shift operations
|
|
810
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
811
|
+
*
|
|
812
|
+
* // Pop removes from the end
|
|
813
|
+
* const last = list.pop();
|
|
814
|
+
* console.log(last); // 50;
|
|
815
|
+
*
|
|
816
|
+
* // Shift removes from the beginning
|
|
817
|
+
* const first = list.shift();
|
|
818
|
+
* console.log(first); // 10;
|
|
819
|
+
*
|
|
820
|
+
* // Verify remaining elements
|
|
821
|
+
* console.log([...list]); // [20, 30, 40];
|
|
822
|
+
* console.log(list.length); // 3;
|
|
823
|
+
*/
|
|
811
824
|
pop() {
|
|
812
825
|
var _a;
|
|
813
826
|
if (!this.head) return void 0;
|
|
@@ -827,10 +840,26 @@ var linkedListTyped = (() => {
|
|
|
827
840
|
return value;
|
|
828
841
|
}
|
|
829
842
|
/**
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
843
|
+
* Remove and return the head element.
|
|
844
|
+
* @remarks Time O(1), Space O(1)
|
|
845
|
+
* @returns Removed element or undefined.
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
* @example
|
|
858
|
+
* // Remove from the front
|
|
859
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30]);
|
|
860
|
+
* console.log(list.shift()); // 10;
|
|
861
|
+
* console.log(list.length); // 2;
|
|
862
|
+
*/
|
|
834
863
|
shift() {
|
|
835
864
|
if (!this.head) return void 0;
|
|
836
865
|
const removed = this.head;
|
|
@@ -840,11 +869,42 @@ var linkedListTyped = (() => {
|
|
|
840
869
|
return removed.value;
|
|
841
870
|
}
|
|
842
871
|
/**
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
872
|
+
* Prepend an element/node to the head.
|
|
873
|
+
* @remarks Time O(1), Space O(1)
|
|
874
|
+
* @param elementOrNode - Element or node to prepend.
|
|
875
|
+
* @returns True when prepended.
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
* @example
|
|
888
|
+
* // SinglyLinkedList unshift and forward traversal
|
|
889
|
+
* const list = new SinglyLinkedList<number>([20, 30, 40]);
|
|
890
|
+
*
|
|
891
|
+
* // Unshift adds to the beginning
|
|
892
|
+
* list.unshift(10);
|
|
893
|
+
* console.log([...list]); // [10, 20, 30, 40];
|
|
894
|
+
*
|
|
895
|
+
* // Access elements (forward traversal only for singly linked)
|
|
896
|
+
* const second = list.at(1);
|
|
897
|
+
* console.log(second); // 20;
|
|
898
|
+
*
|
|
899
|
+
* // SinglyLinkedList allows forward iteration only
|
|
900
|
+
* const elements: number[] = [];
|
|
901
|
+
* for (const item of list) {
|
|
902
|
+
* elements.push(item);
|
|
903
|
+
* }
|
|
904
|
+
* console.log(elements); // [10, 20, 30, 40];
|
|
905
|
+
*
|
|
906
|
+
* console.log(list.length); // 4;
|
|
907
|
+
*/
|
|
848
908
|
unshift(elementOrNode) {
|
|
849
909
|
const newNode = this._ensureNode(elementOrNode);
|
|
850
910
|
if (!this.head) {
|
|
@@ -900,11 +960,28 @@ var linkedListTyped = (() => {
|
|
|
900
960
|
return void 0;
|
|
901
961
|
}
|
|
902
962
|
/**
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
963
|
+
* Get the element at a given index.
|
|
964
|
+
* @remarks Time O(N), Space O(1)
|
|
965
|
+
* @param index - Zero-based index.
|
|
966
|
+
* @returns Element or undefined.
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
* @example
|
|
979
|
+
* // Access element by index
|
|
980
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
|
|
981
|
+
* console.log(list.at(0)); // 'a';
|
|
982
|
+
* console.log(list.at(2)); // 'c';
|
|
983
|
+
* console.log(list.at(3)); // 'd';
|
|
984
|
+
*/
|
|
908
985
|
at(index) {
|
|
909
986
|
if (index < 0 || index >= this._length) return void 0;
|
|
910
987
|
let current = this.head;
|
|
@@ -921,11 +998,23 @@ var linkedListTyped = (() => {
|
|
|
921
998
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
922
999
|
}
|
|
923
1000
|
/**
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1001
|
+
* Get the node reference at a given index.
|
|
1002
|
+
* @remarks Time O(N), Space O(1)
|
|
1003
|
+
* @param index - Zero-based index.
|
|
1004
|
+
* @returns Node or undefined.
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
* @example
|
|
1014
|
+
* // Get node at index
|
|
1015
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1016
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
1017
|
+
*/
|
|
929
1018
|
getNodeAt(index) {
|
|
930
1019
|
if (index < 0 || index >= this._length) return void 0;
|
|
931
1020
|
let current = this.head;
|
|
@@ -933,11 +1022,24 @@ var linkedListTyped = (() => {
|
|
|
933
1022
|
return current;
|
|
934
1023
|
}
|
|
935
1024
|
/**
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1025
|
+
* Delete the element at an index.
|
|
1026
|
+
* @remarks Time O(N), Space O(1)
|
|
1027
|
+
* @param index - Zero-based index.
|
|
1028
|
+
* @returns Removed element or undefined.
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
* @example
|
|
1038
|
+
* // Remove by index
|
|
1039
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1040
|
+
* list.deleteAt(1);
|
|
1041
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
1042
|
+
*/
|
|
941
1043
|
deleteAt(index) {
|
|
942
1044
|
if (index < 0 || index >= this._length) return void 0;
|
|
943
1045
|
if (index === 0) return this.shift();
|
|
@@ -950,11 +1052,24 @@ var linkedListTyped = (() => {
|
|
|
950
1052
|
return value;
|
|
951
1053
|
}
|
|
952
1054
|
/**
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1055
|
+
* Delete the first match by value/node.
|
|
1056
|
+
* @remarks Time O(N), Space O(1)
|
|
1057
|
+
* @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
|
|
1058
|
+
* @returns True if removed.
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
* @example
|
|
1068
|
+
* // Remove first occurrence
|
|
1069
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
|
|
1070
|
+
* list.delete(2);
|
|
1071
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
1072
|
+
*/
|
|
958
1073
|
delete(elementOrNode) {
|
|
959
1074
|
if (elementOrNode === void 0 || !this.head) return false;
|
|
960
1075
|
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
@@ -971,12 +1086,25 @@ var linkedListTyped = (() => {
|
|
|
971
1086
|
return true;
|
|
972
1087
|
}
|
|
973
1088
|
/**
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1089
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
1090
|
+
* @remarks Time O(N), Space O(1)
|
|
1091
|
+
* @param index - Zero-based index.
|
|
1092
|
+
* @param newElementOrNode - Element or node to insert.
|
|
1093
|
+
* @returns True if inserted.
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
* @example
|
|
1103
|
+
* // Insert at index
|
|
1104
|
+
* const list = new SinglyLinkedList<number>([1, 3]);
|
|
1105
|
+
* list.addAt(1, 2);
|
|
1106
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
1107
|
+
*/
|
|
980
1108
|
addAt(index, newElementOrNode) {
|
|
981
1109
|
if (index < 0 || index > this._length) return false;
|
|
982
1110
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1002,28 +1130,70 @@ var linkedListTyped = (() => {
|
|
|
1002
1130
|
return true;
|
|
1003
1131
|
}
|
|
1004
1132
|
/**
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1133
|
+
* Check whether the list is empty.
|
|
1134
|
+
* @remarks Time O(1), Space O(1)
|
|
1135
|
+
* @returns True if length is 0.
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
* @example
|
|
1146
|
+
* // Check empty
|
|
1147
|
+
* console.log(new SinglyLinkedList().isEmpty()); // true;
|
|
1148
|
+
*/
|
|
1009
1149
|
isEmpty() {
|
|
1010
1150
|
return this._length === 0;
|
|
1011
1151
|
}
|
|
1012
1152
|
/**
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1153
|
+
* Remove all nodes and reset length.
|
|
1154
|
+
* @remarks Time O(N), Space O(1)
|
|
1155
|
+
* @returns void
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
* @example
|
|
1166
|
+
* // Remove all
|
|
1167
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1168
|
+
* list.clear();
|
|
1169
|
+
* console.log(list.isEmpty()); // true;
|
|
1170
|
+
*/
|
|
1017
1171
|
clear() {
|
|
1018
1172
|
this._head = void 0;
|
|
1019
1173
|
this._tail = void 0;
|
|
1020
1174
|
this._length = 0;
|
|
1021
1175
|
}
|
|
1022
1176
|
/**
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1177
|
+
* Reverse the list in place.
|
|
1178
|
+
* @remarks Time O(N), Space O(1)
|
|
1179
|
+
* @returns This list.
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
* @example
|
|
1192
|
+
* // Reverse the list in-place
|
|
1193
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
|
|
1194
|
+
* list.reverse();
|
|
1195
|
+
* console.log([...list]); // [4, 3, 2, 1];
|
|
1196
|
+
*/
|
|
1027
1197
|
reverse() {
|
|
1028
1198
|
if (!this.head || this.head === this.tail) return this;
|
|
1029
1199
|
let prev;
|
|
@@ -1198,22 +1368,64 @@ var linkedListTyped = (() => {
|
|
|
1198
1368
|
return false;
|
|
1199
1369
|
}
|
|
1200
1370
|
/**
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1371
|
+
* Deep clone this list (values are copied by reference).
|
|
1372
|
+
* @remarks Time O(N), Space O(N)
|
|
1373
|
+
* @returns A new list with the same element sequence.
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
* @example
|
|
1384
|
+
* // Deep copy
|
|
1385
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1386
|
+
* const copy = list.clone();
|
|
1387
|
+
* copy.pop();
|
|
1388
|
+
* console.log(list.length); // 3;
|
|
1389
|
+
* console.log(copy.length); // 2;
|
|
1390
|
+
*/
|
|
1205
1391
|
clone() {
|
|
1206
1392
|
const out = this._createInstance();
|
|
1207
1393
|
for (const v of this) out.push(v);
|
|
1208
1394
|
return out;
|
|
1209
1395
|
}
|
|
1210
1396
|
/**
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1397
|
+
* Filter values into a new list of the same class.
|
|
1398
|
+
* @remarks Time O(N), Space O(N)
|
|
1399
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
1400
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1401
|
+
* @returns A new list with kept values.
|
|
1402
|
+
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
* @example
|
|
1414
|
+
* // SinglyLinkedList filter and map operations
|
|
1415
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
1416
|
+
*
|
|
1417
|
+
* // Filter even numbers
|
|
1418
|
+
* const filtered = list.filter(value => value % 2 === 0);
|
|
1419
|
+
* console.log(filtered.length); // 2;
|
|
1420
|
+
*
|
|
1421
|
+
* // Map to double values
|
|
1422
|
+
* const doubled = list.map(value => value * 2);
|
|
1423
|
+
* console.log(doubled.length); // 5;
|
|
1424
|
+
*
|
|
1425
|
+
* // Use reduce to sum
|
|
1426
|
+
* const sum = list.reduce((acc, value) => acc + value, 0);
|
|
1427
|
+
* console.log(sum); // 15;
|
|
1428
|
+
*/
|
|
1217
1429
|
filter(callback, thisArg) {
|
|
1218
1430
|
const out = this._createInstance();
|
|
1219
1431
|
let index = 0;
|
|
@@ -1237,15 +1449,31 @@ var linkedListTyped = (() => {
|
|
|
1237
1449
|
return out;
|
|
1238
1450
|
}
|
|
1239
1451
|
/**
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1452
|
+
* Map values into a new list (possibly different element type).
|
|
1453
|
+
* @remarks Time O(N), Space O(N)
|
|
1454
|
+
* @template EM
|
|
1455
|
+
* @template RM
|
|
1456
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1457
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1458
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1459
|
+
* @returns A new SinglyLinkedList with mapped values.
|
|
1460
|
+
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
* @example
|
|
1472
|
+
* // Transform elements
|
|
1473
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1474
|
+
* const doubled = list.map(n => n * 2);
|
|
1475
|
+
* console.log([...doubled]); // [2, 4, 6];
|
|
1476
|
+
*/
|
|
1249
1477
|
map(callback, options, thisArg) {
|
|
1250
1478
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1251
1479
|
let index = 0;
|
|
@@ -1516,11 +1744,37 @@ var linkedListTyped = (() => {
|
|
|
1516
1744
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
1517
1745
|
}
|
|
1518
1746
|
/**
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1747
|
+
* Append an element/node to the tail.
|
|
1748
|
+
* @remarks Time O(1), Space O(1)
|
|
1749
|
+
* @param elementOrNode - Element or node to append.
|
|
1750
|
+
* @returns True when appended.
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
* @example
|
|
1763
|
+
* // basic DoublyLinkedList creation and push operation
|
|
1764
|
+
* // Create a simple DoublyLinkedList with initial values
|
|
1765
|
+
* const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
|
1766
|
+
*
|
|
1767
|
+
* // Verify the list maintains insertion order
|
|
1768
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
1769
|
+
*
|
|
1770
|
+
* // Check length
|
|
1771
|
+
* console.log(list.length); // 5;
|
|
1772
|
+
*
|
|
1773
|
+
* // Push a new element to the end
|
|
1774
|
+
* list.push(6);
|
|
1775
|
+
* console.log(list.length); // 6;
|
|
1776
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
1777
|
+
*/
|
|
1524
1778
|
push(elementOrNode) {
|
|
1525
1779
|
const newNode = this._ensureNode(elementOrNode);
|
|
1526
1780
|
if (!this.head) {
|
|
@@ -1536,10 +1790,36 @@ var linkedListTyped = (() => {
|
|
|
1536
1790
|
return true;
|
|
1537
1791
|
}
|
|
1538
1792
|
/**
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1793
|
+
* Remove and return the tail element.
|
|
1794
|
+
* @remarks Time O(1), Space O(1)
|
|
1795
|
+
* @returns Removed element or undefined.
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
|
|
1807
|
+
* @example
|
|
1808
|
+
* // DoublyLinkedList pop and shift operations
|
|
1809
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
1810
|
+
*
|
|
1811
|
+
* // Pop removes from the end
|
|
1812
|
+
* const last = list.pop();
|
|
1813
|
+
* console.log(last); // 50;
|
|
1814
|
+
*
|
|
1815
|
+
* // Shift removes from the beginning
|
|
1816
|
+
* const first = list.shift();
|
|
1817
|
+
* console.log(first); // 10;
|
|
1818
|
+
*
|
|
1819
|
+
* // Verify remaining elements
|
|
1820
|
+
* console.log([...list]); // [20, 30, 40];
|
|
1821
|
+
* console.log(list.length); // 3;
|
|
1822
|
+
*/
|
|
1543
1823
|
pop() {
|
|
1544
1824
|
if (!this.tail) return void 0;
|
|
1545
1825
|
const removed = this.tail;
|
|
@@ -1554,10 +1834,26 @@ var linkedListTyped = (() => {
|
|
|
1554
1834
|
return removed.value;
|
|
1555
1835
|
}
|
|
1556
1836
|
/**
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1837
|
+
* Remove and return the head element.
|
|
1838
|
+
* @remarks Time O(1), Space O(1)
|
|
1839
|
+
* @returns Removed element or undefined.
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
|
|
1851
|
+
* @example
|
|
1852
|
+
* // Remove from the front
|
|
1853
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
1854
|
+
* console.log(list.shift()); // 10;
|
|
1855
|
+
* console.log(list.first); // 20;
|
|
1856
|
+
*/
|
|
1561
1857
|
shift() {
|
|
1562
1858
|
if (!this.head) return void 0;
|
|
1563
1859
|
const removed = this.head;
|
|
@@ -1572,11 +1868,27 @@ var linkedListTyped = (() => {
|
|
|
1572
1868
|
return removed.value;
|
|
1573
1869
|
}
|
|
1574
1870
|
/**
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1871
|
+
* Prepend an element/node to the head.
|
|
1872
|
+
* @remarks Time O(1), Space O(1)
|
|
1873
|
+
* @param elementOrNode - Element or node to prepend.
|
|
1874
|
+
* @returns True when prepended.
|
|
1875
|
+
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
* @example
|
|
1887
|
+
* // Add to the front
|
|
1888
|
+
* const list = new DoublyLinkedList<number>([2, 3]);
|
|
1889
|
+
* list.unshift(1);
|
|
1890
|
+
* console.log([...list]); // [1, 2, 3];
|
|
1891
|
+
*/
|
|
1580
1892
|
unshift(elementOrNode) {
|
|
1581
1893
|
const newNode = this._ensureNode(elementOrNode);
|
|
1582
1894
|
if (!this.head) {
|
|
@@ -1620,11 +1932,27 @@ var linkedListTyped = (() => {
|
|
|
1620
1932
|
return ans;
|
|
1621
1933
|
}
|
|
1622
1934
|
/**
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1935
|
+
* Get the element at a given index.
|
|
1936
|
+
* @remarks Time O(N), Space O(1)
|
|
1937
|
+
* @param index - Zero-based index.
|
|
1938
|
+
* @returns Element or undefined.
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
|
|
1948
|
+
|
|
1949
|
+
|
|
1950
|
+
* @example
|
|
1951
|
+
* // Access by index
|
|
1952
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
1953
|
+
* console.log(list.at(1)); // 'b';
|
|
1954
|
+
* console.log(list.at(2)); // 'c';
|
|
1955
|
+
*/
|
|
1628
1956
|
at(index) {
|
|
1629
1957
|
if (index < 0 || index >= this._length) return void 0;
|
|
1630
1958
|
let current = this.head;
|
|
@@ -1632,11 +1960,23 @@ var linkedListTyped = (() => {
|
|
|
1632
1960
|
return current == null ? void 0 : current.value;
|
|
1633
1961
|
}
|
|
1634
1962
|
/**
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1963
|
+
* Get the node reference at a given index.
|
|
1964
|
+
* @remarks Time O(N), Space O(1)
|
|
1965
|
+
* @param index - Zero-based index.
|
|
1966
|
+
* @returns Node or undefined.
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
|
|
1975
|
+
* @example
|
|
1976
|
+
* // Get node at index
|
|
1977
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
1978
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
1979
|
+
*/
|
|
1640
1980
|
getNodeAt(index) {
|
|
1641
1981
|
if (index < 0 || index >= this._length) return void 0;
|
|
1642
1982
|
let current = this.head;
|
|
@@ -1675,12 +2015,25 @@ var linkedListTyped = (() => {
|
|
|
1675
2015
|
return void 0;
|
|
1676
2016
|
}
|
|
1677
2017
|
/**
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
2018
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
2019
|
+
* @remarks Time O(N), Space O(1)
|
|
2020
|
+
* @param index - Zero-based index.
|
|
2021
|
+
* @param newElementOrNode - Element or node to insert.
|
|
2022
|
+
* @returns True if inserted.
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
|
|
2030
|
+
|
|
2031
|
+
* @example
|
|
2032
|
+
* // Insert at position
|
|
2033
|
+
* const list = new DoublyLinkedList<number>([1, 3]);
|
|
2034
|
+
* list.addAt(1, 2);
|
|
2035
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
2036
|
+
*/
|
|
1684
2037
|
addAt(index, newElementOrNode) {
|
|
1685
2038
|
if (index < 0 || index > this._length) return false;
|
|
1686
2039
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1747,11 +2100,24 @@ var linkedListTyped = (() => {
|
|
|
1747
2100
|
return true;
|
|
1748
2101
|
}
|
|
1749
2102
|
/**
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
2103
|
+
* Delete the element at an index.
|
|
2104
|
+
* @remarks Time O(N), Space O(1)
|
|
2105
|
+
* @param index - Zero-based index.
|
|
2106
|
+
* @returns Removed element or undefined.
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
* @example
|
|
2116
|
+
* // Remove by index
|
|
2117
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2118
|
+
* list.deleteAt(1);
|
|
2119
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
2120
|
+
*/
|
|
1755
2121
|
deleteAt(index) {
|
|
1756
2122
|
if (index < 0 || index >= this._length) return;
|
|
1757
2123
|
if (index === 0) return this.shift();
|
|
@@ -1765,11 +2131,24 @@ var linkedListTyped = (() => {
|
|
|
1765
2131
|
return removedNode.value;
|
|
1766
2132
|
}
|
|
1767
2133
|
/**
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
2134
|
+
* Delete the first match by value/node.
|
|
2135
|
+
* @remarks Time O(N), Space O(1)
|
|
2136
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
2137
|
+
* @returns True if removed.
|
|
2138
|
+
|
|
2139
|
+
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
|
|
2143
|
+
|
|
2144
|
+
|
|
2145
|
+
|
|
2146
|
+
* @example
|
|
2147
|
+
* // Remove first occurrence
|
|
2148
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
|
|
2149
|
+
* list.delete(2);
|
|
2150
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
2151
|
+
*/
|
|
1773
2152
|
delete(elementOrNode) {
|
|
1774
2153
|
const node = this.getNode(elementOrNode);
|
|
1775
2154
|
if (!node) return false;
|
|
@@ -1785,29 +2164,68 @@ var linkedListTyped = (() => {
|
|
|
1785
2164
|
return true;
|
|
1786
2165
|
}
|
|
1787
2166
|
/**
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2167
|
+
* Check whether the list is empty.
|
|
2168
|
+
* @remarks Time O(1), Space O(1)
|
|
2169
|
+
* @returns True if length is 0.
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
* @example
|
|
2180
|
+
* // Check empty
|
|
2181
|
+
* console.log(new DoublyLinkedList().isEmpty()); // true;
|
|
2182
|
+
*/
|
|
1792
2183
|
isEmpty() {
|
|
1793
2184
|
return this._length === 0;
|
|
1794
2185
|
}
|
|
1795
2186
|
/**
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2187
|
+
* Remove all nodes and reset length.
|
|
2188
|
+
* @remarks Time O(N), Space O(1)
|
|
2189
|
+
* @returns void
|
|
2190
|
+
|
|
2191
|
+
|
|
2192
|
+
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
|
|
2196
|
+
|
|
2197
|
+
|
|
2198
|
+
|
|
2199
|
+
* @example
|
|
2200
|
+
* // Remove all
|
|
2201
|
+
* const list = new DoublyLinkedList<number>([1, 2]);
|
|
2202
|
+
* list.clear();
|
|
2203
|
+
* console.log(list.isEmpty()); // true;
|
|
2204
|
+
*/
|
|
1800
2205
|
clear() {
|
|
1801
2206
|
this._head = void 0;
|
|
1802
2207
|
this._tail = void 0;
|
|
1803
2208
|
this._length = 0;
|
|
1804
2209
|
}
|
|
1805
2210
|
/**
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
2211
|
+
* Find the first value matching a predicate scanning forward.
|
|
2212
|
+
* @remarks Time O(N), Space O(1)
|
|
2213
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2214
|
+
* @returns Matched value or undefined.
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
* @example
|
|
2224
|
+
* // Search with predicate
|
|
2225
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2226
|
+
* const found = list.search(node => node.value > 15);
|
|
2227
|
+
* console.log(found); // 20;
|
|
2228
|
+
*/
|
|
1811
2229
|
search(elementNodeOrPredicate) {
|
|
1812
2230
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1813
2231
|
let current = this.head;
|
|
@@ -1818,11 +2236,25 @@ var linkedListTyped = (() => {
|
|
|
1818
2236
|
return void 0;
|
|
1819
2237
|
}
|
|
1820
2238
|
/**
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
2239
|
+
* Find the first value matching a predicate scanning backward.
|
|
2240
|
+
* @remarks Time O(N), Space O(1)
|
|
2241
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2242
|
+
* @returns Matched value or undefined.
|
|
2243
|
+
|
|
2244
|
+
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
|
|
2248
|
+
|
|
2249
|
+
|
|
2250
|
+
|
|
2251
|
+
* @example
|
|
2252
|
+
* // Find value scanning from tail
|
|
2253
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
|
|
2254
|
+
* // getBackward scans from tail to head, returns first match
|
|
2255
|
+
* const found = list.getBackward(node => node.value < 4);
|
|
2256
|
+
* console.log(found); // 3;
|
|
2257
|
+
*/
|
|
1826
2258
|
getBackward(elementNodeOrPredicate) {
|
|
1827
2259
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1828
2260
|
let current = this.tail;
|
|
@@ -1833,10 +2265,26 @@ var linkedListTyped = (() => {
|
|
|
1833
2265
|
return void 0;
|
|
1834
2266
|
}
|
|
1835
2267
|
/**
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2268
|
+
* Reverse the list in place.
|
|
2269
|
+
* @remarks Time O(N), Space O(1)
|
|
2270
|
+
* @returns This list.
|
|
2271
|
+
|
|
2272
|
+
|
|
2273
|
+
|
|
2274
|
+
|
|
2275
|
+
|
|
2276
|
+
|
|
2277
|
+
|
|
2278
|
+
|
|
2279
|
+
|
|
2280
|
+
|
|
2281
|
+
|
|
2282
|
+
* @example
|
|
2283
|
+
* // Reverse in-place
|
|
2284
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2285
|
+
* list.reverse();
|
|
2286
|
+
* console.log([...list]); // [3, 2, 1];
|
|
2287
|
+
*/
|
|
1840
2288
|
reverse() {
|
|
1841
2289
|
let current = this.head;
|
|
1842
2290
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1858,22 +2306,53 @@ var linkedListTyped = (() => {
|
|
|
1858
2306
|
return this;
|
|
1859
2307
|
}
|
|
1860
2308
|
/**
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2309
|
+
* Deep clone this list (values are copied by reference).
|
|
2310
|
+
* @remarks Time O(N), Space O(N)
|
|
2311
|
+
* @returns A new list with the same element sequence.
|
|
2312
|
+
|
|
2313
|
+
|
|
2314
|
+
|
|
2315
|
+
|
|
2316
|
+
|
|
2317
|
+
|
|
2318
|
+
|
|
2319
|
+
|
|
2320
|
+
|
|
2321
|
+
* @example
|
|
2322
|
+
* // Deep copy
|
|
2323
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2324
|
+
* const copy = list.clone();
|
|
2325
|
+
* copy.pop();
|
|
2326
|
+
* console.log(list.length); // 3;
|
|
2327
|
+
*/
|
|
1865
2328
|
clone() {
|
|
1866
2329
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1867
2330
|
for (const v of this) out.push(v);
|
|
1868
2331
|
return out;
|
|
1869
2332
|
}
|
|
1870
2333
|
/**
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
2334
|
+
* Filter values into a new list of the same class.
|
|
2335
|
+
* @remarks Time O(N), Space O(N)
|
|
2336
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
2337
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2338
|
+
* @returns A new list with kept values.
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
|
|
2342
|
+
|
|
2343
|
+
|
|
2344
|
+
|
|
2345
|
+
|
|
2346
|
+
|
|
2347
|
+
|
|
2348
|
+
|
|
2349
|
+
|
|
2350
|
+
* @example
|
|
2351
|
+
* // Filter elements
|
|
2352
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
2353
|
+
* const evens = list.filter(n => n % 2 === 0);
|
|
2354
|
+
* console.log([...evens]); // [2, 4];
|
|
2355
|
+
*/
|
|
1877
2356
|
filter(callback, thisArg) {
|
|
1878
2357
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1879
2358
|
let index = 0;
|
|
@@ -1897,15 +2376,40 @@ var linkedListTyped = (() => {
|
|
|
1897
2376
|
return out;
|
|
1898
2377
|
}
|
|
1899
2378
|
/**
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
2379
|
+
* Map values into a new list (possibly different element type).
|
|
2380
|
+
* @remarks Time O(N), Space O(N)
|
|
2381
|
+
* @template EM
|
|
2382
|
+
* @template RM
|
|
2383
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
2384
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
2385
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2386
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
2387
|
+
|
|
2388
|
+
|
|
2389
|
+
|
|
2390
|
+
|
|
2391
|
+
|
|
2392
|
+
|
|
2393
|
+
|
|
2394
|
+
|
|
2395
|
+
|
|
2396
|
+
|
|
2397
|
+
|
|
2398
|
+
* @example
|
|
2399
|
+
* // DoublyLinkedList for...of iteration and map operation
|
|
2400
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
2401
|
+
*
|
|
2402
|
+
* // Iterate through list
|
|
2403
|
+
* const doubled = list.map(value => value * 2);
|
|
2404
|
+
* console.log(doubled.length); // 5;
|
|
2405
|
+
*
|
|
2406
|
+
* // Use for...of loop
|
|
2407
|
+
* const result: number[] = [];
|
|
2408
|
+
* for (const item of list) {
|
|
2409
|
+
* result.push(item);
|
|
2410
|
+
* }
|
|
2411
|
+
* console.log(result); // [1, 2, 3, 4, 5];
|
|
2412
|
+
*/
|
|
1909
2413
|
map(callback, options, thisArg) {
|
|
1910
2414
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1911
2415
|
let index = 0;
|
|
@@ -1994,6 +2498,231 @@ var linkedListTyped = (() => {
|
|
|
1994
2498
|
}
|
|
1995
2499
|
};
|
|
1996
2500
|
|
|
2501
|
+
// src/common/error.ts
|
|
2502
|
+
var ERR = {
|
|
2503
|
+
// Range / index
|
|
2504
|
+
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
2505
|
+
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
2506
|
+
// Type / argument
|
|
2507
|
+
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
2508
|
+
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
2509
|
+
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
2510
|
+
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
2511
|
+
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
2512
|
+
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
2513
|
+
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
2514
|
+
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
2515
|
+
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
2516
|
+
// State / operation
|
|
2517
|
+
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
2518
|
+
// Matrix
|
|
2519
|
+
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
2520
|
+
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
2521
|
+
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
2522
|
+
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
2523
|
+
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
2524
|
+
};
|
|
2525
|
+
|
|
2526
|
+
// src/common/index.ts
|
|
2527
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
2528
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
2529
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
2530
|
+
return DFSOperation2;
|
|
2531
|
+
})(DFSOperation || {});
|
|
2532
|
+
var Range = class {
|
|
2533
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
2534
|
+
this.low = low;
|
|
2535
|
+
this.high = high;
|
|
2536
|
+
this.includeLow = includeLow;
|
|
2537
|
+
this.includeHigh = includeHigh;
|
|
2538
|
+
}
|
|
2539
|
+
// Determine whether a key is within the range
|
|
2540
|
+
isInRange(key, comparator) {
|
|
2541
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
2542
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
2543
|
+
return lowCheck && highCheck;
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2547
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
2548
|
+
var IterableEntryBase = class {
|
|
2549
|
+
/**
|
|
2550
|
+
* Default iterator yielding `[key, value]` entries.
|
|
2551
|
+
* @returns Iterator of `[K, V]`.
|
|
2552
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
2553
|
+
*/
|
|
2554
|
+
*[Symbol.iterator](...args) {
|
|
2555
|
+
yield* this._getIterator(...args);
|
|
2556
|
+
}
|
|
2557
|
+
/**
|
|
2558
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
2559
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
2560
|
+
* @remarks Time O(n), Space O(1)
|
|
2561
|
+
*/
|
|
2562
|
+
*entries() {
|
|
2563
|
+
for (const item of this) {
|
|
2564
|
+
yield item;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
/**
|
|
2568
|
+
* Iterate over keys only.
|
|
2569
|
+
* @returns Iterator of keys.
|
|
2570
|
+
* @remarks Time O(n), Space O(1)
|
|
2571
|
+
*/
|
|
2572
|
+
*keys() {
|
|
2573
|
+
for (const item of this) {
|
|
2574
|
+
yield item[0];
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
/**
|
|
2578
|
+
* Iterate over values only.
|
|
2579
|
+
* @returns Iterator of values.
|
|
2580
|
+
* @remarks Time O(n), Space O(1)
|
|
2581
|
+
*/
|
|
2582
|
+
*values() {
|
|
2583
|
+
for (const item of this) {
|
|
2584
|
+
yield item[1];
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
/**
|
|
2588
|
+
* Test whether all entries satisfy the predicate.
|
|
2589
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
2590
|
+
* @param thisArg - Optional `this` for callback.
|
|
2591
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
2592
|
+
* @remarks Time O(n), Space O(1)
|
|
2593
|
+
*/
|
|
2594
|
+
every(predicate, thisArg) {
|
|
2595
|
+
let index = 0;
|
|
2596
|
+
for (const item of this) {
|
|
2597
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
2598
|
+
return false;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
return true;
|
|
2602
|
+
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Test whether any entry satisfies the predicate.
|
|
2605
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
2606
|
+
* @param thisArg - Optional `this` for callback.
|
|
2607
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
2608
|
+
* @remarks Time O(n), Space O(1)
|
|
2609
|
+
*/
|
|
2610
|
+
some(predicate, thisArg) {
|
|
2611
|
+
let index = 0;
|
|
2612
|
+
for (const item of this) {
|
|
2613
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
2614
|
+
return true;
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Visit each entry, left-to-right.
|
|
2621
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
2622
|
+
* @param thisArg - Optional `this` for callback.
|
|
2623
|
+
* @remarks Time O(n), Space O(1)
|
|
2624
|
+
*/
|
|
2625
|
+
forEach(callbackfn, thisArg) {
|
|
2626
|
+
let index = 0;
|
|
2627
|
+
for (const item of this) {
|
|
2628
|
+
const [key, value] = item;
|
|
2629
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
/**
|
|
2633
|
+
* Find the first entry that matches a predicate.
|
|
2634
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
2635
|
+
* @param thisArg - Optional `this` for callback.
|
|
2636
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
2637
|
+
* @remarks Time O(n), Space O(1)
|
|
2638
|
+
*/
|
|
2639
|
+
find(callbackfn, thisArg) {
|
|
2640
|
+
let index = 0;
|
|
2641
|
+
for (const item of this) {
|
|
2642
|
+
const [key, value] = item;
|
|
2643
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
2644
|
+
}
|
|
2645
|
+
return;
|
|
2646
|
+
}
|
|
2647
|
+
/**
|
|
2648
|
+
* Whether the given key exists.
|
|
2649
|
+
* @param key - Key to test.
|
|
2650
|
+
* @returns `true` if found; otherwise `false`.
|
|
2651
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
2652
|
+
*/
|
|
2653
|
+
has(key) {
|
|
2654
|
+
for (const item of this) {
|
|
2655
|
+
const [itemKey] = item;
|
|
2656
|
+
if (itemKey === key) return true;
|
|
2657
|
+
}
|
|
2658
|
+
return false;
|
|
2659
|
+
}
|
|
2660
|
+
/**
|
|
2661
|
+
* Whether there exists an entry with the given value.
|
|
2662
|
+
* @param value - Value to test.
|
|
2663
|
+
* @returns `true` if found; otherwise `false`.
|
|
2664
|
+
* @remarks Time O(n), Space O(1)
|
|
2665
|
+
*/
|
|
2666
|
+
hasValue(value) {
|
|
2667
|
+
for (const [, elementValue] of this) {
|
|
2668
|
+
if (elementValue === value) return true;
|
|
2669
|
+
}
|
|
2670
|
+
return false;
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* Get the value under a key.
|
|
2674
|
+
* @param key - Key to look up.
|
|
2675
|
+
* @returns Value or `undefined`.
|
|
2676
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
2677
|
+
*/
|
|
2678
|
+
get(key) {
|
|
2679
|
+
for (const item of this) {
|
|
2680
|
+
const [itemKey, value] = item;
|
|
2681
|
+
if (itemKey === key) return value;
|
|
2682
|
+
}
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
/**
|
|
2686
|
+
* Reduce entries into a single accumulator.
|
|
2687
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
2688
|
+
* @param initialValue - Initial accumulator.
|
|
2689
|
+
* @returns Final accumulator.
|
|
2690
|
+
* @remarks Time O(n), Space O(1)
|
|
2691
|
+
*/
|
|
2692
|
+
reduce(callbackfn, initialValue) {
|
|
2693
|
+
let accumulator = initialValue;
|
|
2694
|
+
let index = 0;
|
|
2695
|
+
for (const item of this) {
|
|
2696
|
+
const [key, value] = item;
|
|
2697
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
2698
|
+
}
|
|
2699
|
+
return accumulator;
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Converts data structure to `[key, value]` pairs.
|
|
2703
|
+
* @returns Array of entries.
|
|
2704
|
+
* @remarks Time O(n), Space O(n)
|
|
2705
|
+
*/
|
|
2706
|
+
toArray() {
|
|
2707
|
+
return [...this];
|
|
2708
|
+
}
|
|
2709
|
+
/**
|
|
2710
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
2711
|
+
* @returns Array of entries (default) or a string.
|
|
2712
|
+
* @remarks Time O(n), Space O(n)
|
|
2713
|
+
*/
|
|
2714
|
+
toVisual() {
|
|
2715
|
+
return [...this];
|
|
2716
|
+
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Print a human-friendly representation to the console.
|
|
2719
|
+
* @remarks Time O(n), Space O(n)
|
|
2720
|
+
*/
|
|
2721
|
+
print() {
|
|
2722
|
+
console.log(this.toVisual());
|
|
2723
|
+
}
|
|
2724
|
+
};
|
|
2725
|
+
|
|
1997
2726
|
// src/data-structures/linked-list/skip-linked-list.ts
|
|
1998
2727
|
var SkipListNode = class {
|
|
1999
2728
|
constructor(key, value, level) {
|
|
@@ -2002,29 +2731,67 @@ var linkedListTyped = (() => {
|
|
|
2002
2731
|
__publicField(this, "forward");
|
|
2003
2732
|
this.key = key;
|
|
2004
2733
|
this.value = value;
|
|
2005
|
-
this.forward = new Array(level);
|
|
2734
|
+
this.forward = new Array(level).fill(void 0);
|
|
2006
2735
|
}
|
|
2007
2736
|
};
|
|
2008
|
-
var
|
|
2009
|
-
|
|
2010
|
-
|
|
2737
|
+
var _comparator, _isDefaultComparator;
|
|
2738
|
+
var _SkipList = class _SkipList extends IterableEntryBase {
|
|
2739
|
+
constructor(entries = [], options = {}) {
|
|
2740
|
+
super();
|
|
2741
|
+
__privateAdd(this, _comparator);
|
|
2742
|
+
__privateAdd(this, _isDefaultComparator);
|
|
2743
|
+
// ─── Internal state ──────────────────────────────────────────
|
|
2744
|
+
__publicField(this, "_head");
|
|
2011
2745
|
__publicField(this, "_level", 0);
|
|
2746
|
+
__publicField(this, "_size", 0);
|
|
2012
2747
|
__publicField(this, "_maxLevel", 16);
|
|
2013
2748
|
__publicField(this, "_probability", 0.5);
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2749
|
+
const { comparator, toEntryFn, maxLevel, probability } = options;
|
|
2750
|
+
if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
|
|
2751
|
+
if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
|
|
2752
|
+
__privateSet(this, _isDefaultComparator, comparator === void 0);
|
|
2753
|
+
__privateSet(this, _comparator, comparator != null ? comparator : _SkipList.createDefaultComparator());
|
|
2754
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
2755
|
+
for (const item of entries) {
|
|
2756
|
+
let k;
|
|
2757
|
+
let v;
|
|
2758
|
+
if (toEntryFn) {
|
|
2759
|
+
[k, v] = toEntryFn(item);
|
|
2760
|
+
} else {
|
|
2761
|
+
if (!Array.isArray(item) || item.length < 2) {
|
|
2762
|
+
throw new TypeError(ERR.invalidEntry("SkipList"));
|
|
2763
|
+
}
|
|
2764
|
+
[k, v] = item;
|
|
2765
|
+
}
|
|
2766
|
+
this.set(k, v);
|
|
2021
2767
|
}
|
|
2022
2768
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2769
|
+
/**
|
|
2770
|
+
* Creates a default comparator supporting number, string, Date, and bigint.
|
|
2771
|
+
*/
|
|
2772
|
+
static createDefaultComparator() {
|
|
2773
|
+
return (a, b) => {
|
|
2774
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
2775
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
|
|
2776
|
+
return a - b;
|
|
2777
|
+
}
|
|
2778
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
2779
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
2780
|
+
}
|
|
2781
|
+
if (a instanceof Date && b instanceof Date) {
|
|
2782
|
+
const ta = a.getTime(), tb = b.getTime();
|
|
2783
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
|
|
2784
|
+
return ta - tb;
|
|
2785
|
+
}
|
|
2786
|
+
if (typeof a === "bigint" && typeof b === "bigint") {
|
|
2787
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
2788
|
+
}
|
|
2789
|
+
throw new TypeError(ERR.comparatorRequired("SkipList"));
|
|
2790
|
+
};
|
|
2025
2791
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2792
|
+
// ─── Size & lifecycle ────────────────────────────────────────
|
|
2793
|
+
get size() {
|
|
2794
|
+
return this._size;
|
|
2028
2795
|
}
|
|
2029
2796
|
get maxLevel() {
|
|
2030
2797
|
return this._maxLevel;
|
|
@@ -2032,108 +2799,593 @@ var linkedListTyped = (() => {
|
|
|
2032
2799
|
get probability() {
|
|
2033
2800
|
return this._probability;
|
|
2034
2801
|
}
|
|
2035
|
-
get
|
|
2036
|
-
|
|
2037
|
-
|
|
2802
|
+
get comparator() {
|
|
2803
|
+
return __privateGet(this, _comparator);
|
|
2804
|
+
}
|
|
2805
|
+
/**
|
|
2806
|
+
* Check if empty
|
|
2807
|
+
|
|
2808
|
+
|
|
2809
|
+
|
|
2810
|
+
|
|
2811
|
+
|
|
2812
|
+
|
|
2813
|
+
|
|
2814
|
+
|
|
2815
|
+
* @example
|
|
2816
|
+
* // Check if empty
|
|
2817
|
+
* const sl = new SkipList<number, string>();
|
|
2818
|
+
* console.log(sl.isEmpty()); // true;
|
|
2819
|
+
*/
|
|
2820
|
+
isEmpty() {
|
|
2821
|
+
return this._size === 0;
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Remove all entries
|
|
2825
|
+
|
|
2826
|
+
|
|
2827
|
+
|
|
2828
|
+
|
|
2829
|
+
|
|
2830
|
+
|
|
2831
|
+
|
|
2832
|
+
|
|
2833
|
+
* @example
|
|
2834
|
+
* // Remove all entries
|
|
2835
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
2836
|
+
* sl.clear();
|
|
2837
|
+
* console.log(sl.isEmpty()); // true;
|
|
2838
|
+
*/
|
|
2839
|
+
clear() {
|
|
2840
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
2841
|
+
this._level = 0;
|
|
2842
|
+
this._size = 0;
|
|
2843
|
+
}
|
|
2844
|
+
/**
|
|
2845
|
+
* Create independent copy
|
|
2846
|
+
|
|
2847
|
+
|
|
2848
|
+
|
|
2849
|
+
|
|
2850
|
+
|
|
2851
|
+
|
|
2852
|
+
|
|
2853
|
+
|
|
2854
|
+
* @example
|
|
2855
|
+
* // Create independent copy
|
|
2856
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
2857
|
+
* const copy = sl.clone();
|
|
2858
|
+
* copy.delete(1);
|
|
2859
|
+
* console.log(sl.has(1)); // true;
|
|
2860
|
+
*/
|
|
2861
|
+
clone() {
|
|
2862
|
+
return new _SkipList(this, {
|
|
2863
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
2864
|
+
maxLevel: this._maxLevel,
|
|
2865
|
+
probability: this._probability
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
// ─── Core CRUD ───────────────────────────────────────────────
|
|
2869
|
+
/**
|
|
2870
|
+
* Insert or update a key-value pair. Returns `this` for chaining.
|
|
2871
|
+
* Unique keys only — if key exists, value is updated in place.
|
|
2872
|
+
|
|
2873
|
+
|
|
2874
|
+
|
|
2875
|
+
|
|
2876
|
+
|
|
2877
|
+
|
|
2878
|
+
|
|
2879
|
+
|
|
2880
|
+
|
|
2881
|
+
|
|
2882
|
+
|
|
2883
|
+
* @example
|
|
2884
|
+
* // In-memory sorted key-value store
|
|
2885
|
+
* const store = new SkipList<number, string>();
|
|
2886
|
+
*
|
|
2887
|
+
* store.set(3, 'three');
|
|
2888
|
+
* store.set(1, 'one');
|
|
2889
|
+
* store.set(5, 'five');
|
|
2890
|
+
* store.set(2, 'two');
|
|
2891
|
+
*
|
|
2892
|
+
* console.log(store.get(3)); // 'three';
|
|
2893
|
+
* console.log(store.get(1)); // 'one';
|
|
2894
|
+
* console.log(store.get(5)); // 'five';
|
|
2895
|
+
*
|
|
2896
|
+
* // Update existing key
|
|
2897
|
+
* store.set(3, 'THREE');
|
|
2898
|
+
* console.log(store.get(3)); // 'THREE';
|
|
2899
|
+
*/
|
|
2900
|
+
set(key, value) {
|
|
2901
|
+
const cmp = __privateGet(this, _comparator);
|
|
2902
|
+
const update = this._findUpdate(key);
|
|
2903
|
+
const existing = update[0].forward[0];
|
|
2904
|
+
if (existing && cmp(existing.key, key) === 0) {
|
|
2905
|
+
existing.value = value;
|
|
2906
|
+
return this;
|
|
2907
|
+
}
|
|
2908
|
+
const newLevel = this._randomLevel();
|
|
2909
|
+
const newNode = new SkipListNode(key, value, newLevel);
|
|
2910
|
+
if (newLevel > this._level) {
|
|
2911
|
+
for (let i = this._level; i < newLevel; i++) {
|
|
2912
|
+
update[i] = this._head;
|
|
2913
|
+
}
|
|
2914
|
+
this._level = newLevel;
|
|
2915
|
+
}
|
|
2916
|
+
for (let i = 0; i < newLevel; i++) {
|
|
2917
|
+
newNode.forward[i] = update[i].forward[i];
|
|
2918
|
+
update[i].forward[i] = newNode;
|
|
2919
|
+
}
|
|
2920
|
+
this._size++;
|
|
2921
|
+
return this;
|
|
2038
2922
|
}
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2923
|
+
/**
|
|
2924
|
+
* Get the value for a key, or `undefined` if not found.
|
|
2925
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
2926
|
+
|
|
2927
|
+
|
|
2928
|
+
|
|
2929
|
+
|
|
2930
|
+
|
|
2931
|
+
|
|
2932
|
+
|
|
2933
|
+
|
|
2934
|
+
|
|
2935
|
+
|
|
2936
|
+
|
|
2937
|
+
* @example
|
|
2938
|
+
* // Building a sorted index
|
|
2939
|
+
* type Product = { id: number; name: string; price: number };
|
|
2940
|
+
* const products: Product[] = [
|
|
2941
|
+
* { id: 1, name: 'Widget', price: 25 },
|
|
2942
|
+
* { id: 2, name: 'Gadget', price: 50 },
|
|
2943
|
+
* { id: 3, name: 'Doohickey', price: 15 }
|
|
2944
|
+
* ];
|
|
2945
|
+
*
|
|
2946
|
+
* const index = new SkipList<number, Product>(products as any, {
|
|
2947
|
+
* toEntryFn: (p: any) => [p.price, p]
|
|
2948
|
+
* });
|
|
2949
|
+
*
|
|
2950
|
+
* // Iterate in sorted order by price
|
|
2951
|
+
* const names = [...index.values()].map(p => p!.name);
|
|
2952
|
+
* console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
|
|
2953
|
+
*
|
|
2954
|
+
* // Range search: products between $20 and $60
|
|
2955
|
+
* const range = index.rangeSearch([20, 60]);
|
|
2956
|
+
* console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
|
|
2957
|
+
*/
|
|
2958
|
+
get(key) {
|
|
2959
|
+
const node = this._findNode(key);
|
|
2960
|
+
return node ? node.value : void 0;
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Check if a key exists.
|
|
2964
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
2965
|
+
|
|
2966
|
+
|
|
2967
|
+
|
|
2968
|
+
|
|
2969
|
+
|
|
2970
|
+
|
|
2971
|
+
|
|
2972
|
+
|
|
2973
|
+
|
|
2974
|
+
|
|
2975
|
+
|
|
2976
|
+
* @example
|
|
2977
|
+
* // Check key existence
|
|
2978
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
|
|
2979
|
+
* console.log(sl.has(3)); // true;
|
|
2980
|
+
* console.log(sl.has(4)); // false;
|
|
2981
|
+
*/
|
|
2982
|
+
has(key) {
|
|
2983
|
+
return this._findNode(key) !== void 0;
|
|
2984
|
+
}
|
|
2985
|
+
/**
|
|
2986
|
+
* Delete a key. Returns `true` if the key was found and removed.
|
|
2987
|
+
|
|
2988
|
+
|
|
2989
|
+
|
|
2990
|
+
|
|
2991
|
+
|
|
2992
|
+
|
|
2993
|
+
|
|
2994
|
+
|
|
2995
|
+
|
|
2996
|
+
|
|
2997
|
+
|
|
2998
|
+
* @example
|
|
2999
|
+
* // Fast lookup with deletion
|
|
3000
|
+
* const cache = new SkipList<string, number>();
|
|
3001
|
+
*
|
|
3002
|
+
* cache.set('alpha', 1);
|
|
3003
|
+
* cache.set('beta', 2);
|
|
3004
|
+
* cache.set('gamma', 3);
|
|
3005
|
+
*
|
|
3006
|
+
* console.log(cache.has('beta')); // true;
|
|
3007
|
+
* cache.delete('beta');
|
|
3008
|
+
* console.log(cache.has('beta')); // false;
|
|
3009
|
+
* console.log(cache.size); // 2;
|
|
3010
|
+
*/
|
|
3011
|
+
delete(key) {
|
|
3012
|
+
const cmp = __privateGet(this, _comparator);
|
|
3013
|
+
const update = this._findUpdate(key);
|
|
3014
|
+
const target = update[0].forward[0];
|
|
3015
|
+
if (!target || cmp(target.key, key) !== 0) return false;
|
|
3016
|
+
for (let i = 0; i < this._level; i++) {
|
|
3017
|
+
if (update[i].forward[i] !== target) break;
|
|
3018
|
+
update[i].forward[i] = target.forward[i];
|
|
3019
|
+
}
|
|
3020
|
+
while (this._level > 0 && !this._head.forward[this._level - 1]) {
|
|
3021
|
+
this._level--;
|
|
3022
|
+
}
|
|
3023
|
+
this._size--;
|
|
3024
|
+
return true;
|
|
3025
|
+
}
|
|
3026
|
+
// ─── Navigation ──────────────────────────────────────────────
|
|
3027
|
+
/**
|
|
3028
|
+
* Returns the first (smallest key) entry, or `undefined` if empty.
|
|
3029
|
+
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
|
|
3033
|
+
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
|
|
3037
|
+
|
|
3038
|
+
|
|
3039
|
+
|
|
3040
|
+
* @example
|
|
3041
|
+
* // Access the minimum entry
|
|
3042
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3043
|
+
* console.log(sl.first()); // [1, 'a'];
|
|
3044
|
+
*/
|
|
3045
|
+
first() {
|
|
3046
|
+
const node = this._head.forward[0];
|
|
3047
|
+
return node ? [node.key, node.value] : void 0;
|
|
3048
|
+
}
|
|
3049
|
+
/**
|
|
3050
|
+
* Returns the last (largest key) entry, or `undefined` if empty.
|
|
3051
|
+
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
|
|
3055
|
+
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
|
|
3059
|
+
|
|
3060
|
+
|
|
3061
|
+
|
|
3062
|
+
* @example
|
|
3063
|
+
* // Access the maximum entry
|
|
3064
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3065
|
+
* console.log(sl.last()); // [5, 'e'];
|
|
3066
|
+
*/
|
|
3067
|
+
last() {
|
|
3068
|
+
let current = this._head;
|
|
3069
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
2042
3070
|
while (current.forward[i]) {
|
|
2043
3071
|
current = current.forward[i];
|
|
2044
3072
|
}
|
|
2045
3073
|
}
|
|
2046
|
-
return current.value;
|
|
2047
|
-
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
3074
|
+
return current === this._head ? void 0 : [current.key, current.value];
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Remove and return the first (smallest key) entry.
|
|
3078
|
+
|
|
3079
|
+
|
|
3080
|
+
|
|
3081
|
+
|
|
3082
|
+
|
|
3083
|
+
|
|
3084
|
+
|
|
3085
|
+
|
|
3086
|
+
* @example
|
|
3087
|
+
* // Remove and return smallest
|
|
3088
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3089
|
+
* console.log(sl.pollFirst()); // [1, 'a'];
|
|
3090
|
+
* console.log(sl.size); // 2;
|
|
3091
|
+
*/
|
|
3092
|
+
pollFirst() {
|
|
3093
|
+
const entry = this.first();
|
|
3094
|
+
if (!entry) return void 0;
|
|
3095
|
+
this.delete(entry[0]);
|
|
3096
|
+
return entry;
|
|
3097
|
+
}
|
|
3098
|
+
/**
|
|
3099
|
+
* Remove and return the last (largest key) entry.
|
|
3100
|
+
|
|
3101
|
+
|
|
3102
|
+
|
|
3103
|
+
|
|
3104
|
+
|
|
3105
|
+
|
|
3106
|
+
|
|
3107
|
+
|
|
3108
|
+
* @example
|
|
3109
|
+
* // Remove and return largest
|
|
3110
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3111
|
+
* console.log(sl.pollLast()); // [3, 'c'];
|
|
3112
|
+
* console.log(sl.size); // 2;
|
|
3113
|
+
*/
|
|
3114
|
+
pollLast() {
|
|
3115
|
+
const entry = this.last();
|
|
3116
|
+
if (!entry) return void 0;
|
|
3117
|
+
this.delete(entry[0]);
|
|
3118
|
+
return entry;
|
|
3119
|
+
}
|
|
3120
|
+
/**
|
|
3121
|
+
* Least entry ≥ key, or `undefined`.
|
|
3122
|
+
|
|
3123
|
+
|
|
3124
|
+
|
|
3125
|
+
|
|
3126
|
+
|
|
3127
|
+
|
|
3128
|
+
|
|
3129
|
+
|
|
3130
|
+
|
|
3131
|
+
|
|
3132
|
+
|
|
3133
|
+
* @example
|
|
3134
|
+
* // Least entry ≥ key
|
|
3135
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3136
|
+
* console.log(sl.ceiling(15)); // [20, 'b'];
|
|
3137
|
+
* console.log(sl.ceiling(20)); // [20, 'b'];
|
|
3138
|
+
*/
|
|
3139
|
+
ceiling(key) {
|
|
3140
|
+
const cmp = __privateGet(this, _comparator);
|
|
3141
|
+
let current = this._head;
|
|
3142
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3143
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2054
3144
|
current = current.forward[i];
|
|
2055
3145
|
}
|
|
2056
|
-
update[i] = current;
|
|
2057
3146
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
3147
|
+
const node = current.forward[0];
|
|
3148
|
+
return node ? [node.key, node.value] : void 0;
|
|
3149
|
+
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Greatest entry ≤ key, or `undefined`.
|
|
3152
|
+
|
|
3153
|
+
|
|
3154
|
+
|
|
3155
|
+
|
|
3156
|
+
|
|
3157
|
+
|
|
3158
|
+
|
|
3159
|
+
|
|
3160
|
+
|
|
3161
|
+
|
|
3162
|
+
|
|
3163
|
+
* @example
|
|
3164
|
+
* // Greatest entry ≤ key
|
|
3165
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3166
|
+
* console.log(sl.floor(25)); // [20, 'b'];
|
|
3167
|
+
* console.log(sl.floor(5)); // undefined;
|
|
3168
|
+
*/
|
|
3169
|
+
floor(key) {
|
|
3170
|
+
const cmp = __privateGet(this, _comparator);
|
|
3171
|
+
let current = this._head;
|
|
3172
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3173
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
3174
|
+
current = current.forward[i];
|
|
3175
|
+
}
|
|
2064
3176
|
}
|
|
3177
|
+
const result = current === this._head ? void 0 : current;
|
|
3178
|
+
if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
|
|
3179
|
+
return void 0;
|
|
2065
3180
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
3181
|
+
/**
|
|
3182
|
+
* Least entry strictly > key, or `undefined`.
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
|
|
3190
|
+
|
|
3191
|
+
* @example
|
|
3192
|
+
* // Strictly greater entry
|
|
3193
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3194
|
+
* console.log(sl.higher(15)); // [20, 'b'];
|
|
3195
|
+
* console.log(sl.higher(30)); // undefined;
|
|
3196
|
+
*/
|
|
3197
|
+
higher(key) {
|
|
3198
|
+
const cmp = __privateGet(this, _comparator);
|
|
3199
|
+
let current = this._head;
|
|
3200
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3201
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
2070
3202
|
current = current.forward[i];
|
|
2071
3203
|
}
|
|
2072
3204
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
3205
|
+
const node = current.forward[0];
|
|
3206
|
+
return node ? [node.key, node.value] : void 0;
|
|
3207
|
+
}
|
|
3208
|
+
/**
|
|
3209
|
+
* Greatest entry strictly < key, or `undefined`.
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
|
|
3213
|
+
|
|
3214
|
+
|
|
3215
|
+
|
|
3216
|
+
|
|
3217
|
+
|
|
3218
|
+
* @example
|
|
3219
|
+
* // Strictly less entry
|
|
3220
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3221
|
+
* console.log(sl.lower(25)); // [20, 'b'];
|
|
3222
|
+
* console.log(sl.lower(10)); // undefined;
|
|
3223
|
+
*/
|
|
3224
|
+
lower(key) {
|
|
3225
|
+
const cmp = __privateGet(this, _comparator);
|
|
3226
|
+
let current = this._head;
|
|
3227
|
+
let result;
|
|
3228
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3229
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
3230
|
+
current = current.forward[i];
|
|
3231
|
+
}
|
|
3232
|
+
if (current !== this._head && cmp(current.key, key) < 0) {
|
|
3233
|
+
result = current;
|
|
3234
|
+
}
|
|
2076
3235
|
}
|
|
2077
|
-
return void 0;
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
3236
|
+
return result ? [result.key, result.value] : void 0;
|
|
3237
|
+
}
|
|
3238
|
+
/**
|
|
3239
|
+
* Returns entries within the given key range.
|
|
3240
|
+
|
|
3241
|
+
|
|
3242
|
+
|
|
3243
|
+
|
|
3244
|
+
|
|
3245
|
+
|
|
3246
|
+
|
|
3247
|
+
|
|
3248
|
+
|
|
3249
|
+
|
|
3250
|
+
|
|
3251
|
+
* @example
|
|
3252
|
+
* // Find entries in a range
|
|
3253
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
|
|
3254
|
+
* const result = sl.rangeSearch([2, 4]);
|
|
3255
|
+
* console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
3256
|
+
*/
|
|
3257
|
+
rangeSearch(range, options = {}) {
|
|
3258
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
3259
|
+
const [low, high] = range;
|
|
3260
|
+
const cmp = __privateGet(this, _comparator);
|
|
3261
|
+
const out = [];
|
|
3262
|
+
let current = this._head;
|
|
3263
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3264
|
+
while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
|
|
2087
3265
|
current = current.forward[i];
|
|
2088
3266
|
}
|
|
2089
|
-
update[i] = current;
|
|
2090
3267
|
}
|
|
2091
3268
|
current = current.forward[0];
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
while (this.level > 0 && !this.head.forward[this.level - 1]) {
|
|
2100
|
-
this._level--;
|
|
3269
|
+
while (current) {
|
|
3270
|
+
const cmpHigh = cmp(current.key, high);
|
|
3271
|
+
if (cmpHigh > 0) break;
|
|
3272
|
+
if (cmpHigh === 0 && !highInclusive) break;
|
|
3273
|
+
const cmpLow = cmp(current.key, low);
|
|
3274
|
+
if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
|
|
3275
|
+
out.push([current.key, current.value]);
|
|
2101
3276
|
}
|
|
2102
|
-
|
|
3277
|
+
current = current.forward[0];
|
|
2103
3278
|
}
|
|
2104
|
-
return
|
|
3279
|
+
return out;
|
|
2105
3280
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
3281
|
+
// ─── Functional (overrides) ──────────────────────────────────
|
|
3282
|
+
/**
|
|
3283
|
+
* Creates a new SkipList with entries transformed by callback.
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
|
|
3291
|
+
|
|
3292
|
+
* @example
|
|
3293
|
+
* // Transform entries
|
|
3294
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3295
|
+
* const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
|
|
3296
|
+
* console.log([...mapped.values()]); // ['A', 'B'];
|
|
3297
|
+
*/
|
|
3298
|
+
map(callback, options) {
|
|
3299
|
+
const out = new _SkipList([], options != null ? options : {});
|
|
3300
|
+
let i = 0;
|
|
3301
|
+
for (const [k, v] of this) {
|
|
3302
|
+
const [nk, nv] = callback(v, k, i++, this);
|
|
3303
|
+
out.set(nk, nv);
|
|
3304
|
+
}
|
|
3305
|
+
return out;
|
|
3306
|
+
}
|
|
3307
|
+
/**
|
|
3308
|
+
* Creates a new SkipList with entries that pass the predicate.
|
|
3309
|
+
|
|
3310
|
+
|
|
3311
|
+
|
|
3312
|
+
|
|
3313
|
+
|
|
3314
|
+
|
|
3315
|
+
|
|
3316
|
+
|
|
3317
|
+
* @example
|
|
3318
|
+
* // Filter entries
|
|
3319
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3320
|
+
* const result = sl.filter((v, k) => k > 1);
|
|
3321
|
+
* console.log(result.size); // 2;
|
|
3322
|
+
*/
|
|
3323
|
+
filter(callbackfn, thisArg) {
|
|
3324
|
+
const out = new _SkipList([], {
|
|
3325
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
3326
|
+
maxLevel: this._maxLevel,
|
|
3327
|
+
probability: this._probability
|
|
3328
|
+
});
|
|
3329
|
+
let i = 0;
|
|
3330
|
+
for (const [k, v] of this) {
|
|
3331
|
+
const ok = callbackfn.call(thisArg, v, k, i++, this);
|
|
3332
|
+
if (ok) out.set(k, v);
|
|
3333
|
+
}
|
|
3334
|
+
return out;
|
|
3335
|
+
}
|
|
3336
|
+
// ─── Iterator (required by IterableEntryBase) ────────────────
|
|
3337
|
+
_getIterator() {
|
|
3338
|
+
const head = this._head;
|
|
3339
|
+
return (function* () {
|
|
3340
|
+
let node = head.forward[0];
|
|
3341
|
+
while (node) {
|
|
3342
|
+
yield [node.key, node.value];
|
|
3343
|
+
node = node.forward[0];
|
|
3344
|
+
}
|
|
3345
|
+
})();
|
|
3346
|
+
}
|
|
3347
|
+
// ─── Internal helpers ────────────────────────────────────────
|
|
3348
|
+
/**
|
|
3349
|
+
* Finds the update array (predecessors at each level) for a given key.
|
|
3350
|
+
*/
|
|
3351
|
+
_findUpdate(key) {
|
|
3352
|
+
const cmp = __privateGet(this, _comparator);
|
|
3353
|
+
const update = new Array(this._maxLevel).fill(this._head);
|
|
3354
|
+
let current = this._head;
|
|
3355
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3356
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2110
3357
|
current = current.forward[i];
|
|
2111
3358
|
}
|
|
3359
|
+
update[i] = current;
|
|
2112
3360
|
}
|
|
2113
|
-
|
|
2114
|
-
return nextNode ? nextNode.value : void 0;
|
|
3361
|
+
return update;
|
|
2115
3362
|
}
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
3363
|
+
/**
|
|
3364
|
+
* Finds the node for a given key, or undefined.
|
|
3365
|
+
*/
|
|
3366
|
+
_findNode(key) {
|
|
3367
|
+
const cmp = __privateGet(this, _comparator);
|
|
3368
|
+
let current = this._head;
|
|
3369
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3370
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2121
3371
|
current = current.forward[i];
|
|
2122
3372
|
}
|
|
2123
|
-
if (current.key < key) {
|
|
2124
|
-
lastLess = current;
|
|
2125
|
-
}
|
|
2126
3373
|
}
|
|
2127
|
-
|
|
3374
|
+
const candidate = current.forward[0];
|
|
3375
|
+
if (candidate && cmp(candidate.key, key) === 0) return candidate;
|
|
3376
|
+
return void 0;
|
|
2128
3377
|
}
|
|
2129
3378
|
_randomLevel() {
|
|
2130
3379
|
let level = 1;
|
|
2131
|
-
while (Math.random() < this.
|
|
3380
|
+
while (Math.random() < this._probability && level < this._maxLevel) {
|
|
2132
3381
|
level++;
|
|
2133
3382
|
}
|
|
2134
3383
|
return level;
|
|
2135
3384
|
}
|
|
2136
3385
|
};
|
|
3386
|
+
_comparator = new WeakMap();
|
|
3387
|
+
_isDefaultComparator = new WeakMap();
|
|
3388
|
+
var SkipList = _SkipList;
|
|
2137
3389
|
return __toCommonJS(src_exports);
|
|
2138
3390
|
})();
|
|
2139
3391
|
/**
|