linked-list-typed 2.4.4 → 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 +1537 -267
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1543 -264
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1537 -268
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1543 -265
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- 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 +439 -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 +217 -31
- 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/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -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 +313 -66
- 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/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/linked-list-typed.js +1540 -262
- 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/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- 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 +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- 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 +343 -68
- 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 +215 -44
- 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
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -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 = {};
|
|
@@ -26,6 +33,7 @@ var linkedListTyped = (() => {
|
|
|
26
33
|
DFSOperation: () => DFSOperation,
|
|
27
34
|
DoublyLinkedList: () => DoublyLinkedList,
|
|
28
35
|
DoublyLinkedListNode: () => DoublyLinkedListNode,
|
|
36
|
+
ERR: () => ERR,
|
|
29
37
|
Range: () => Range,
|
|
30
38
|
SinglyLinkedList: () => SinglyLinkedList,
|
|
31
39
|
SinglyLinkedListNode: () => SinglyLinkedListNode,
|
|
@@ -739,11 +747,37 @@ var linkedListTyped = (() => {
|
|
|
739
747
|
return list;
|
|
740
748
|
}
|
|
741
749
|
/**
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
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
|
+
*/
|
|
747
781
|
push(elementOrNode) {
|
|
748
782
|
const newNode = this._ensureNode(elementOrNode);
|
|
749
783
|
if (!this.head) {
|
|
@@ -757,10 +791,36 @@ var linkedListTyped = (() => {
|
|
|
757
791
|
return true;
|
|
758
792
|
}
|
|
759
793
|
/**
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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
|
+
*/
|
|
764
824
|
pop() {
|
|
765
825
|
var _a;
|
|
766
826
|
if (!this.head) return void 0;
|
|
@@ -780,10 +840,26 @@ var linkedListTyped = (() => {
|
|
|
780
840
|
return value;
|
|
781
841
|
}
|
|
782
842
|
/**
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
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
|
+
*/
|
|
787
863
|
shift() {
|
|
788
864
|
if (!this.head) return void 0;
|
|
789
865
|
const removed = this.head;
|
|
@@ -793,11 +869,42 @@ var linkedListTyped = (() => {
|
|
|
793
869
|
return removed.value;
|
|
794
870
|
}
|
|
795
871
|
/**
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
+
*/
|
|
801
908
|
unshift(elementOrNode) {
|
|
802
909
|
const newNode = this._ensureNode(elementOrNode);
|
|
803
910
|
if (!this.head) {
|
|
@@ -853,11 +960,28 @@ var linkedListTyped = (() => {
|
|
|
853
960
|
return void 0;
|
|
854
961
|
}
|
|
855
962
|
/**
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
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
|
+
*/
|
|
861
985
|
at(index) {
|
|
862
986
|
if (index < 0 || index >= this._length) return void 0;
|
|
863
987
|
let current = this.head;
|
|
@@ -874,11 +998,23 @@ var linkedListTyped = (() => {
|
|
|
874
998
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
875
999
|
}
|
|
876
1000
|
/**
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
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
|
+
*/
|
|
882
1018
|
getNodeAt(index) {
|
|
883
1019
|
if (index < 0 || index >= this._length) return void 0;
|
|
884
1020
|
let current = this.head;
|
|
@@ -886,11 +1022,24 @@ var linkedListTyped = (() => {
|
|
|
886
1022
|
return current;
|
|
887
1023
|
}
|
|
888
1024
|
/**
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
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
|
+
*/
|
|
894
1043
|
deleteAt(index) {
|
|
895
1044
|
if (index < 0 || index >= this._length) return void 0;
|
|
896
1045
|
if (index === 0) return this.shift();
|
|
@@ -903,11 +1052,24 @@ var linkedListTyped = (() => {
|
|
|
903
1052
|
return value;
|
|
904
1053
|
}
|
|
905
1054
|
/**
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
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
|
+
*/
|
|
911
1073
|
delete(elementOrNode) {
|
|
912
1074
|
if (elementOrNode === void 0 || !this.head) return false;
|
|
913
1075
|
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
@@ -924,12 +1086,25 @@ var linkedListTyped = (() => {
|
|
|
924
1086
|
return true;
|
|
925
1087
|
}
|
|
926
1088
|
/**
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
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
|
+
*/
|
|
933
1108
|
addAt(index, newElementOrNode) {
|
|
934
1109
|
if (index < 0 || index > this._length) return false;
|
|
935
1110
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -955,28 +1130,70 @@ var linkedListTyped = (() => {
|
|
|
955
1130
|
return true;
|
|
956
1131
|
}
|
|
957
1132
|
/**
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
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
|
+
*/
|
|
962
1149
|
isEmpty() {
|
|
963
1150
|
return this._length === 0;
|
|
964
1151
|
}
|
|
965
1152
|
/**
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
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
|
+
*/
|
|
970
1171
|
clear() {
|
|
971
1172
|
this._head = void 0;
|
|
972
1173
|
this._tail = void 0;
|
|
973
1174
|
this._length = 0;
|
|
974
1175
|
}
|
|
975
1176
|
/**
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
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
|
+
*/
|
|
980
1197
|
reverse() {
|
|
981
1198
|
if (!this.head || this.head === this.tail) return this;
|
|
982
1199
|
let prev;
|
|
@@ -1151,22 +1368,64 @@ var linkedListTyped = (() => {
|
|
|
1151
1368
|
return false;
|
|
1152
1369
|
}
|
|
1153
1370
|
/**
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
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
|
+
*/
|
|
1158
1391
|
clone() {
|
|
1159
1392
|
const out = this._createInstance();
|
|
1160
1393
|
for (const v of this) out.push(v);
|
|
1161
1394
|
return out;
|
|
1162
1395
|
}
|
|
1163
1396
|
/**
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
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
|
+
*/
|
|
1170
1429
|
filter(callback, thisArg) {
|
|
1171
1430
|
const out = this._createInstance();
|
|
1172
1431
|
let index = 0;
|
|
@@ -1190,15 +1449,31 @@ var linkedListTyped = (() => {
|
|
|
1190
1449
|
return out;
|
|
1191
1450
|
}
|
|
1192
1451
|
/**
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
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
|
+
*/
|
|
1202
1477
|
map(callback, options, thisArg) {
|
|
1203
1478
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1204
1479
|
let index = 0;
|
|
@@ -1469,11 +1744,37 @@ var linkedListTyped = (() => {
|
|
|
1469
1744
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
1470
1745
|
}
|
|
1471
1746
|
/**
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
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
|
+
*/
|
|
1477
1778
|
push(elementOrNode) {
|
|
1478
1779
|
const newNode = this._ensureNode(elementOrNode);
|
|
1479
1780
|
if (!this.head) {
|
|
@@ -1489,10 +1790,36 @@ var linkedListTyped = (() => {
|
|
|
1489
1790
|
return true;
|
|
1490
1791
|
}
|
|
1491
1792
|
/**
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
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
|
+
*/
|
|
1496
1823
|
pop() {
|
|
1497
1824
|
if (!this.tail) return void 0;
|
|
1498
1825
|
const removed = this.tail;
|
|
@@ -1507,10 +1834,26 @@ var linkedListTyped = (() => {
|
|
|
1507
1834
|
return removed.value;
|
|
1508
1835
|
}
|
|
1509
1836
|
/**
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
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
|
+
*/
|
|
1514
1857
|
shift() {
|
|
1515
1858
|
if (!this.head) return void 0;
|
|
1516
1859
|
const removed = this.head;
|
|
@@ -1525,11 +1868,27 @@ var linkedListTyped = (() => {
|
|
|
1525
1868
|
return removed.value;
|
|
1526
1869
|
}
|
|
1527
1870
|
/**
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
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
|
+
*/
|
|
1533
1892
|
unshift(elementOrNode) {
|
|
1534
1893
|
const newNode = this._ensureNode(elementOrNode);
|
|
1535
1894
|
if (!this.head) {
|
|
@@ -1573,11 +1932,27 @@ var linkedListTyped = (() => {
|
|
|
1573
1932
|
return ans;
|
|
1574
1933
|
}
|
|
1575
1934
|
/**
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
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
|
+
*/
|
|
1581
1956
|
at(index) {
|
|
1582
1957
|
if (index < 0 || index >= this._length) return void 0;
|
|
1583
1958
|
let current = this.head;
|
|
@@ -1585,11 +1960,23 @@ var linkedListTyped = (() => {
|
|
|
1585
1960
|
return current == null ? void 0 : current.value;
|
|
1586
1961
|
}
|
|
1587
1962
|
/**
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
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
|
+
*/
|
|
1593
1980
|
getNodeAt(index) {
|
|
1594
1981
|
if (index < 0 || index >= this._length) return void 0;
|
|
1595
1982
|
let current = this.head;
|
|
@@ -1628,12 +2015,25 @@ var linkedListTyped = (() => {
|
|
|
1628
2015
|
return void 0;
|
|
1629
2016
|
}
|
|
1630
2017
|
/**
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
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
|
+
*/
|
|
1637
2037
|
addAt(index, newElementOrNode) {
|
|
1638
2038
|
if (index < 0 || index > this._length) return false;
|
|
1639
2039
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1700,11 +2100,24 @@ var linkedListTyped = (() => {
|
|
|
1700
2100
|
return true;
|
|
1701
2101
|
}
|
|
1702
2102
|
/**
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
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
|
+
*/
|
|
1708
2121
|
deleteAt(index) {
|
|
1709
2122
|
if (index < 0 || index >= this._length) return;
|
|
1710
2123
|
if (index === 0) return this.shift();
|
|
@@ -1718,11 +2131,24 @@ var linkedListTyped = (() => {
|
|
|
1718
2131
|
return removedNode.value;
|
|
1719
2132
|
}
|
|
1720
2133
|
/**
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
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
|
+
*/
|
|
1726
2152
|
delete(elementOrNode) {
|
|
1727
2153
|
const node = this.getNode(elementOrNode);
|
|
1728
2154
|
if (!node) return false;
|
|
@@ -1738,29 +2164,68 @@ var linkedListTyped = (() => {
|
|
|
1738
2164
|
return true;
|
|
1739
2165
|
}
|
|
1740
2166
|
/**
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
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
|
+
*/
|
|
1745
2183
|
isEmpty() {
|
|
1746
2184
|
return this._length === 0;
|
|
1747
2185
|
}
|
|
1748
2186
|
/**
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
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
|
+
*/
|
|
1753
2205
|
clear() {
|
|
1754
2206
|
this._head = void 0;
|
|
1755
2207
|
this._tail = void 0;
|
|
1756
2208
|
this._length = 0;
|
|
1757
2209
|
}
|
|
1758
2210
|
/**
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
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
|
+
*/
|
|
1764
2229
|
search(elementNodeOrPredicate) {
|
|
1765
2230
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1766
2231
|
let current = this.head;
|
|
@@ -1771,11 +2236,25 @@ var linkedListTyped = (() => {
|
|
|
1771
2236
|
return void 0;
|
|
1772
2237
|
}
|
|
1773
2238
|
/**
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
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
|
+
*/
|
|
1779
2258
|
getBackward(elementNodeOrPredicate) {
|
|
1780
2259
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1781
2260
|
let current = this.tail;
|
|
@@ -1786,10 +2265,26 @@ var linkedListTyped = (() => {
|
|
|
1786
2265
|
return void 0;
|
|
1787
2266
|
}
|
|
1788
2267
|
/**
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
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
|
+
*/
|
|
1793
2288
|
reverse() {
|
|
1794
2289
|
let current = this.head;
|
|
1795
2290
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1811,22 +2306,53 @@ var linkedListTyped = (() => {
|
|
|
1811
2306
|
return this;
|
|
1812
2307
|
}
|
|
1813
2308
|
/**
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
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
|
+
*/
|
|
1818
2328
|
clone() {
|
|
1819
2329
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1820
2330
|
for (const v of this) out.push(v);
|
|
1821
2331
|
return out;
|
|
1822
2332
|
}
|
|
1823
2333
|
/**
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
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
|
+
*/
|
|
1830
2356
|
filter(callback, thisArg) {
|
|
1831
2357
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1832
2358
|
let index = 0;
|
|
@@ -1850,15 +2376,40 @@ var linkedListTyped = (() => {
|
|
|
1850
2376
|
return out;
|
|
1851
2377
|
}
|
|
1852
2378
|
/**
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
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
|
+
*/
|
|
1862
2413
|
map(callback, options, thisArg) {
|
|
1863
2414
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1864
2415
|
let index = 0;
|
|
@@ -1947,6 +2498,231 @@ var linkedListTyped = (() => {
|
|
|
1947
2498
|
}
|
|
1948
2499
|
};
|
|
1949
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
|
+
|
|
1950
2726
|
// src/data-structures/linked-list/skip-linked-list.ts
|
|
1951
2727
|
var SkipListNode = class {
|
|
1952
2728
|
constructor(key, value, level) {
|
|
@@ -1955,29 +2731,67 @@ var linkedListTyped = (() => {
|
|
|
1955
2731
|
__publicField(this, "forward");
|
|
1956
2732
|
this.key = key;
|
|
1957
2733
|
this.value = value;
|
|
1958
|
-
this.forward = new Array(level);
|
|
2734
|
+
this.forward = new Array(level).fill(void 0);
|
|
1959
2735
|
}
|
|
1960
2736
|
};
|
|
1961
|
-
var
|
|
1962
|
-
|
|
1963
|
-
|
|
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");
|
|
1964
2745
|
__publicField(this, "_level", 0);
|
|
2746
|
+
__publicField(this, "_size", 0);
|
|
1965
2747
|
__publicField(this, "_maxLevel", 16);
|
|
1966
2748
|
__publicField(this, "_probability", 0.5);
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
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);
|
|
1974
2767
|
}
|
|
1975
2768
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
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
|
+
};
|
|
1978
2791
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
2792
|
+
// ─── Size & lifecycle ────────────────────────────────────────
|
|
2793
|
+
get size() {
|
|
2794
|
+
return this._size;
|
|
1981
2795
|
}
|
|
1982
2796
|
get maxLevel() {
|
|
1983
2797
|
return this._maxLevel;
|
|
@@ -1985,129 +2799,593 @@ var linkedListTyped = (() => {
|
|
|
1985
2799
|
get probability() {
|
|
1986
2800
|
return this._probability;
|
|
1987
2801
|
}
|
|
1988
|
-
get
|
|
1989
|
-
|
|
1990
|
-
|
|
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;
|
|
1991
2922
|
}
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
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--) {
|
|
1995
3070
|
while (current.forward[i]) {
|
|
1996
3071
|
current = current.forward[i];
|
|
1997
3072
|
}
|
|
1998
3073
|
}
|
|
1999
|
-
return current.value;
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
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) {
|
|
2007
3144
|
current = current.forward[i];
|
|
2008
3145
|
}
|
|
2009
|
-
update[i] = current;
|
|
2010
|
-
}
|
|
2011
|
-
for (let i = 0; i < newNode.forward.length; i++) {
|
|
2012
|
-
newNode.forward[i] = update[i].forward[i];
|
|
2013
|
-
update[i].forward[i] = newNode;
|
|
2014
3146
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
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
|
+
}
|
|
2017
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;
|
|
2018
3180
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
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) {
|
|
2023
3202
|
current = current.forward[i];
|
|
2024
3203
|
}
|
|
2025
3204
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
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
|
+
}
|
|
2029
3235
|
}
|
|
2030
|
-
return void 0;
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
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) {
|
|
2040
3265
|
current = current.forward[i];
|
|
2041
3266
|
}
|
|
2042
|
-
update[i] = current;
|
|
2043
3267
|
}
|
|
2044
3268
|
current = current.forward[0];
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
while (this.level > 0 && !this.head.forward[this.level - 1]) {
|
|
2053
|
-
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]);
|
|
2054
3276
|
}
|
|
2055
|
-
|
|
3277
|
+
current = current.forward[0];
|
|
2056
3278
|
}
|
|
2057
|
-
return
|
|
3279
|
+
return out;
|
|
2058
3280
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
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) {
|
|
2063
3357
|
current = current.forward[i];
|
|
2064
3358
|
}
|
|
3359
|
+
update[i] = current;
|
|
2065
3360
|
}
|
|
2066
|
-
|
|
2067
|
-
return nextNode ? nextNode.value : void 0;
|
|
3361
|
+
return update;
|
|
2068
3362
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
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) {
|
|
2074
3371
|
current = current.forward[i];
|
|
2075
3372
|
}
|
|
2076
|
-
if (current.key < key) {
|
|
2077
|
-
lastLess = current;
|
|
2078
|
-
}
|
|
2079
3373
|
}
|
|
2080
|
-
|
|
3374
|
+
const candidate = current.forward[0];
|
|
3375
|
+
if (candidate && cmp(candidate.key, key) === 0) return candidate;
|
|
3376
|
+
return void 0;
|
|
2081
3377
|
}
|
|
2082
3378
|
_randomLevel() {
|
|
2083
3379
|
let level = 1;
|
|
2084
|
-
while (Math.random() < this.
|
|
3380
|
+
while (Math.random() < this._probability && level < this._maxLevel) {
|
|
2085
3381
|
level++;
|
|
2086
3382
|
}
|
|
2087
3383
|
return level;
|
|
2088
3384
|
}
|
|
2089
3385
|
};
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
var
|
|
2093
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
2094
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
2095
|
-
return DFSOperation2;
|
|
2096
|
-
})(DFSOperation || {});
|
|
2097
|
-
var Range = class {
|
|
2098
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
2099
|
-
this.low = low;
|
|
2100
|
-
this.high = high;
|
|
2101
|
-
this.includeLow = includeLow;
|
|
2102
|
-
this.includeHigh = includeHigh;
|
|
2103
|
-
}
|
|
2104
|
-
// Determine whether a key is within the range
|
|
2105
|
-
isInRange(key, comparator) {
|
|
2106
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
2107
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
2108
|
-
return lowCheck && highCheck;
|
|
2109
|
-
}
|
|
2110
|
-
};
|
|
3386
|
+
_comparator = new WeakMap();
|
|
3387
|
+
_isDefaultComparator = new WeakMap();
|
|
3388
|
+
var SkipList = _SkipList;
|
|
2111
3389
|
return __toCommonJS(src_exports);
|
|
2112
3390
|
})();
|
|
2113
3391
|
/**
|