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
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
2
5
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
6
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
7
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
9
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
10
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
11
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
5
12
|
|
|
6
13
|
// src/data-structures/base/iterable-element-base.ts
|
|
7
14
|
var _IterableElementBase = class _IterableElementBase {
|
|
@@ -719,11 +726,37 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
719
726
|
return list;
|
|
720
727
|
}
|
|
721
728
|
/**
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
729
|
+
* Append an element/node to the tail.
|
|
730
|
+
* @remarks Time O(1), Space O(1)
|
|
731
|
+
* @param elementOrNode - Element or node to append.
|
|
732
|
+
* @returns True when appended.
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
* @example
|
|
745
|
+
* // basic SinglyLinkedList creation and push operation
|
|
746
|
+
* // Create a simple SinglyLinkedList with initial values
|
|
747
|
+
* const list = new SinglyLinkedList([1, 2, 3, 4, 5]);
|
|
748
|
+
*
|
|
749
|
+
* // Verify the list maintains insertion order
|
|
750
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
751
|
+
*
|
|
752
|
+
* // Check length
|
|
753
|
+
* console.log(list.length); // 5;
|
|
754
|
+
*
|
|
755
|
+
* // Push a new element to the end
|
|
756
|
+
* list.push(6);
|
|
757
|
+
* console.log(list.length); // 6;
|
|
758
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
759
|
+
*/
|
|
727
760
|
push(elementOrNode) {
|
|
728
761
|
const newNode = this._ensureNode(elementOrNode);
|
|
729
762
|
if (!this.head) {
|
|
@@ -737,10 +770,36 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
737
770
|
return true;
|
|
738
771
|
}
|
|
739
772
|
/**
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
773
|
+
* Remove and return the tail element.
|
|
774
|
+
* @remarks Time O(N), Space O(1)
|
|
775
|
+
* @returns Removed element or undefined.
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
* @example
|
|
788
|
+
* // SinglyLinkedList pop and shift operations
|
|
789
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
790
|
+
*
|
|
791
|
+
* // Pop removes from the end
|
|
792
|
+
* const last = list.pop();
|
|
793
|
+
* console.log(last); // 50;
|
|
794
|
+
*
|
|
795
|
+
* // Shift removes from the beginning
|
|
796
|
+
* const first = list.shift();
|
|
797
|
+
* console.log(first); // 10;
|
|
798
|
+
*
|
|
799
|
+
* // Verify remaining elements
|
|
800
|
+
* console.log([...list]); // [20, 30, 40];
|
|
801
|
+
* console.log(list.length); // 3;
|
|
802
|
+
*/
|
|
744
803
|
pop() {
|
|
745
804
|
var _a;
|
|
746
805
|
if (!this.head) return void 0;
|
|
@@ -760,10 +819,26 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
760
819
|
return value;
|
|
761
820
|
}
|
|
762
821
|
/**
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
822
|
+
* Remove and return the head element.
|
|
823
|
+
* @remarks Time O(1), Space O(1)
|
|
824
|
+
* @returns Removed element or undefined.
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
* @example
|
|
837
|
+
* // Remove from the front
|
|
838
|
+
* const list = new SinglyLinkedList<number>([10, 20, 30]);
|
|
839
|
+
* console.log(list.shift()); // 10;
|
|
840
|
+
* console.log(list.length); // 2;
|
|
841
|
+
*/
|
|
767
842
|
shift() {
|
|
768
843
|
if (!this.head) return void 0;
|
|
769
844
|
const removed = this.head;
|
|
@@ -773,11 +848,42 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
773
848
|
return removed.value;
|
|
774
849
|
}
|
|
775
850
|
/**
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
851
|
+
* Prepend an element/node to the head.
|
|
852
|
+
* @remarks Time O(1), Space O(1)
|
|
853
|
+
* @param elementOrNode - Element or node to prepend.
|
|
854
|
+
* @returns True when prepended.
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
* @example
|
|
867
|
+
* // SinglyLinkedList unshift and forward traversal
|
|
868
|
+
* const list = new SinglyLinkedList<number>([20, 30, 40]);
|
|
869
|
+
*
|
|
870
|
+
* // Unshift adds to the beginning
|
|
871
|
+
* list.unshift(10);
|
|
872
|
+
* console.log([...list]); // [10, 20, 30, 40];
|
|
873
|
+
*
|
|
874
|
+
* // Access elements (forward traversal only for singly linked)
|
|
875
|
+
* const second = list.at(1);
|
|
876
|
+
* console.log(second); // 20;
|
|
877
|
+
*
|
|
878
|
+
* // SinglyLinkedList allows forward iteration only
|
|
879
|
+
* const elements: number[] = [];
|
|
880
|
+
* for (const item of list) {
|
|
881
|
+
* elements.push(item);
|
|
882
|
+
* }
|
|
883
|
+
* console.log(elements); // [10, 20, 30, 40];
|
|
884
|
+
*
|
|
885
|
+
* console.log(list.length); // 4;
|
|
886
|
+
*/
|
|
781
887
|
unshift(elementOrNode) {
|
|
782
888
|
const newNode = this._ensureNode(elementOrNode);
|
|
783
889
|
if (!this.head) {
|
|
@@ -833,11 +939,28 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
833
939
|
return void 0;
|
|
834
940
|
}
|
|
835
941
|
/**
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
942
|
+
* Get the element at a given index.
|
|
943
|
+
* @remarks Time O(N), Space O(1)
|
|
944
|
+
* @param index - Zero-based index.
|
|
945
|
+
* @returns Element or undefined.
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
* @example
|
|
958
|
+
* // Access element by index
|
|
959
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c', 'd']);
|
|
960
|
+
* console.log(list.at(0)); // 'a';
|
|
961
|
+
* console.log(list.at(2)); // 'c';
|
|
962
|
+
* console.log(list.at(3)); // 'd';
|
|
963
|
+
*/
|
|
841
964
|
at(index) {
|
|
842
965
|
if (index < 0 || index >= this._length) return void 0;
|
|
843
966
|
let current = this.head;
|
|
@@ -854,11 +977,23 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
854
977
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
855
978
|
}
|
|
856
979
|
/**
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
980
|
+
* Get the node reference at a given index.
|
|
981
|
+
* @remarks Time O(N), Space O(1)
|
|
982
|
+
* @param index - Zero-based index.
|
|
983
|
+
* @returns Node or undefined.
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
* @example
|
|
993
|
+
* // Get node at index
|
|
994
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
995
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
996
|
+
*/
|
|
862
997
|
getNodeAt(index) {
|
|
863
998
|
if (index < 0 || index >= this._length) return void 0;
|
|
864
999
|
let current = this.head;
|
|
@@ -866,11 +1001,24 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
866
1001
|
return current;
|
|
867
1002
|
}
|
|
868
1003
|
/**
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1004
|
+
* Delete the element at an index.
|
|
1005
|
+
* @remarks Time O(N), Space O(1)
|
|
1006
|
+
* @param index - Zero-based index.
|
|
1007
|
+
* @returns Removed element or undefined.
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
* @example
|
|
1017
|
+
* // Remove by index
|
|
1018
|
+
* const list = new SinglyLinkedList<string>(['a', 'b', 'c']);
|
|
1019
|
+
* list.deleteAt(1);
|
|
1020
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
1021
|
+
*/
|
|
874
1022
|
deleteAt(index) {
|
|
875
1023
|
if (index < 0 || index >= this._length) return void 0;
|
|
876
1024
|
if (index === 0) return this.shift();
|
|
@@ -883,11 +1031,24 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
883
1031
|
return value;
|
|
884
1032
|
}
|
|
885
1033
|
/**
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1034
|
+
* Delete the first match by value/node.
|
|
1035
|
+
* @remarks Time O(N), Space O(1)
|
|
1036
|
+
* @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
|
|
1037
|
+
* @returns True if removed.
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
* @example
|
|
1047
|
+
* // Remove first occurrence
|
|
1048
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 2]);
|
|
1049
|
+
* list.delete(2);
|
|
1050
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
1051
|
+
*/
|
|
891
1052
|
delete(elementOrNode) {
|
|
892
1053
|
if (elementOrNode === void 0 || !this.head) return false;
|
|
893
1054
|
const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);
|
|
@@ -904,12 +1065,25 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
904
1065
|
return true;
|
|
905
1066
|
}
|
|
906
1067
|
/**
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1068
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
1069
|
+
* @remarks Time O(N), Space O(1)
|
|
1070
|
+
* @param index - Zero-based index.
|
|
1071
|
+
* @param newElementOrNode - Element or node to insert.
|
|
1072
|
+
* @returns True if inserted.
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
* @example
|
|
1082
|
+
* // Insert at index
|
|
1083
|
+
* const list = new SinglyLinkedList<number>([1, 3]);
|
|
1084
|
+
* list.addAt(1, 2);
|
|
1085
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
1086
|
+
*/
|
|
913
1087
|
addAt(index, newElementOrNode) {
|
|
914
1088
|
if (index < 0 || index > this._length) return false;
|
|
915
1089
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -935,28 +1109,70 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
935
1109
|
return true;
|
|
936
1110
|
}
|
|
937
1111
|
/**
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1112
|
+
* Check whether the list is empty.
|
|
1113
|
+
* @remarks Time O(1), Space O(1)
|
|
1114
|
+
* @returns True if length is 0.
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
* @example
|
|
1125
|
+
* // Check empty
|
|
1126
|
+
* console.log(new SinglyLinkedList().isEmpty()); // true;
|
|
1127
|
+
*/
|
|
942
1128
|
isEmpty() {
|
|
943
1129
|
return this._length === 0;
|
|
944
1130
|
}
|
|
945
1131
|
/**
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1132
|
+
* Remove all nodes and reset length.
|
|
1133
|
+
* @remarks Time O(N), Space O(1)
|
|
1134
|
+
* @returns void
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
* @example
|
|
1145
|
+
* // Remove all
|
|
1146
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1147
|
+
* list.clear();
|
|
1148
|
+
* console.log(list.isEmpty()); // true;
|
|
1149
|
+
*/
|
|
950
1150
|
clear() {
|
|
951
1151
|
this._head = void 0;
|
|
952
1152
|
this._tail = void 0;
|
|
953
1153
|
this._length = 0;
|
|
954
1154
|
}
|
|
955
1155
|
/**
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1156
|
+
* Reverse the list in place.
|
|
1157
|
+
* @remarks Time O(N), Space O(1)
|
|
1158
|
+
* @returns This list.
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
* @example
|
|
1171
|
+
* // Reverse the list in-place
|
|
1172
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
|
|
1173
|
+
* list.reverse();
|
|
1174
|
+
* console.log([...list]); // [4, 3, 2, 1];
|
|
1175
|
+
*/
|
|
960
1176
|
reverse() {
|
|
961
1177
|
if (!this.head || this.head === this.tail) return this;
|
|
962
1178
|
let prev;
|
|
@@ -1131,22 +1347,64 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
1131
1347
|
return false;
|
|
1132
1348
|
}
|
|
1133
1349
|
/**
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1350
|
+
* Deep clone this list (values are copied by reference).
|
|
1351
|
+
* @remarks Time O(N), Space O(N)
|
|
1352
|
+
* @returns A new list with the same element sequence.
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
* @example
|
|
1363
|
+
* // Deep copy
|
|
1364
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1365
|
+
* const copy = list.clone();
|
|
1366
|
+
* copy.pop();
|
|
1367
|
+
* console.log(list.length); // 3;
|
|
1368
|
+
* console.log(copy.length); // 2;
|
|
1369
|
+
*/
|
|
1138
1370
|
clone() {
|
|
1139
1371
|
const out = this._createInstance();
|
|
1140
1372
|
for (const v of this) out.push(v);
|
|
1141
1373
|
return out;
|
|
1142
1374
|
}
|
|
1143
1375
|
/**
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1376
|
+
* Filter values into a new list of the same class.
|
|
1377
|
+
* @remarks Time O(N), Space O(N)
|
|
1378
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
1379
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1380
|
+
* @returns A new list with kept values.
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
* @example
|
|
1393
|
+
* // SinglyLinkedList filter and map operations
|
|
1394
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
1395
|
+
*
|
|
1396
|
+
* // Filter even numbers
|
|
1397
|
+
* const filtered = list.filter(value => value % 2 === 0);
|
|
1398
|
+
* console.log(filtered.length); // 2;
|
|
1399
|
+
*
|
|
1400
|
+
* // Map to double values
|
|
1401
|
+
* const doubled = list.map(value => value * 2);
|
|
1402
|
+
* console.log(doubled.length); // 5;
|
|
1403
|
+
*
|
|
1404
|
+
* // Use reduce to sum
|
|
1405
|
+
* const sum = list.reduce((acc, value) => acc + value, 0);
|
|
1406
|
+
* console.log(sum); // 15;
|
|
1407
|
+
*/
|
|
1150
1408
|
filter(callback, thisArg) {
|
|
1151
1409
|
const out = this._createInstance();
|
|
1152
1410
|
let index = 0;
|
|
@@ -1170,15 +1428,31 @@ var _SinglyLinkedList = class _SinglyLinkedList extends LinearLinkedBase {
|
|
|
1170
1428
|
return out;
|
|
1171
1429
|
}
|
|
1172
1430
|
/**
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1431
|
+
* Map values into a new list (possibly different element type).
|
|
1432
|
+
* @remarks Time O(N), Space O(N)
|
|
1433
|
+
* @template EM
|
|
1434
|
+
* @template RM
|
|
1435
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1436
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1437
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1438
|
+
* @returns A new SinglyLinkedList with mapped values.
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
* @example
|
|
1451
|
+
* // Transform elements
|
|
1452
|
+
* const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
1453
|
+
* const doubled = list.map(n => n * 2);
|
|
1454
|
+
* console.log([...doubled]); // [2, 4, 6];
|
|
1455
|
+
*/
|
|
1182
1456
|
map(callback, options, thisArg) {
|
|
1183
1457
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1184
1458
|
let index = 0;
|
|
@@ -1454,11 +1728,37 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1454
1728
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
1455
1729
|
}
|
|
1456
1730
|
/**
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1731
|
+
* Append an element/node to the tail.
|
|
1732
|
+
* @remarks Time O(1), Space O(1)
|
|
1733
|
+
* @param elementOrNode - Element or node to append.
|
|
1734
|
+
* @returns True when appended.
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
* @example
|
|
1747
|
+
* // basic DoublyLinkedList creation and push operation
|
|
1748
|
+
* // Create a simple DoublyLinkedList with initial values
|
|
1749
|
+
* const list = new DoublyLinkedList([1, 2, 3, 4, 5]);
|
|
1750
|
+
*
|
|
1751
|
+
* // Verify the list maintains insertion order
|
|
1752
|
+
* console.log([...list]); // [1, 2, 3, 4, 5];
|
|
1753
|
+
*
|
|
1754
|
+
* // Check length
|
|
1755
|
+
* console.log(list.length); // 5;
|
|
1756
|
+
*
|
|
1757
|
+
* // Push a new element to the end
|
|
1758
|
+
* list.push(6);
|
|
1759
|
+
* console.log(list.length); // 6;
|
|
1760
|
+
* console.log([...list]); // [1, 2, 3, 4, 5, 6];
|
|
1761
|
+
*/
|
|
1462
1762
|
push(elementOrNode) {
|
|
1463
1763
|
const newNode = this._ensureNode(elementOrNode);
|
|
1464
1764
|
if (!this.head) {
|
|
@@ -1474,10 +1774,36 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1474
1774
|
return true;
|
|
1475
1775
|
}
|
|
1476
1776
|
/**
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1777
|
+
* Remove and return the tail element.
|
|
1778
|
+
* @remarks Time O(1), Space O(1)
|
|
1779
|
+
* @returns Removed element or undefined.
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
|
|
1791
|
+
* @example
|
|
1792
|
+
* // DoublyLinkedList pop and shift operations
|
|
1793
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30, 40, 50]);
|
|
1794
|
+
*
|
|
1795
|
+
* // Pop removes from the end
|
|
1796
|
+
* const last = list.pop();
|
|
1797
|
+
* console.log(last); // 50;
|
|
1798
|
+
*
|
|
1799
|
+
* // Shift removes from the beginning
|
|
1800
|
+
* const first = list.shift();
|
|
1801
|
+
* console.log(first); // 10;
|
|
1802
|
+
*
|
|
1803
|
+
* // Verify remaining elements
|
|
1804
|
+
* console.log([...list]); // [20, 30, 40];
|
|
1805
|
+
* console.log(list.length); // 3;
|
|
1806
|
+
*/
|
|
1481
1807
|
pop() {
|
|
1482
1808
|
if (!this.tail) return void 0;
|
|
1483
1809
|
const removed = this.tail;
|
|
@@ -1492,10 +1818,26 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1492
1818
|
return removed.value;
|
|
1493
1819
|
}
|
|
1494
1820
|
/**
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1821
|
+
* Remove and return the head element.
|
|
1822
|
+
* @remarks Time O(1), Space O(1)
|
|
1823
|
+
* @returns Removed element or undefined.
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
* @example
|
|
1836
|
+
* // Remove from the front
|
|
1837
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
1838
|
+
* console.log(list.shift()); // 10;
|
|
1839
|
+
* console.log(list.first); // 20;
|
|
1840
|
+
*/
|
|
1499
1841
|
shift() {
|
|
1500
1842
|
if (!this.head) return void 0;
|
|
1501
1843
|
const removed = this.head;
|
|
@@ -1510,11 +1852,27 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1510
1852
|
return removed.value;
|
|
1511
1853
|
}
|
|
1512
1854
|
/**
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1855
|
+
* Prepend an element/node to the head.
|
|
1856
|
+
* @remarks Time O(1), Space O(1)
|
|
1857
|
+
* @param elementOrNode - Element or node to prepend.
|
|
1858
|
+
* @returns True when prepended.
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
* @example
|
|
1871
|
+
* // Add to the front
|
|
1872
|
+
* const list = new DoublyLinkedList<number>([2, 3]);
|
|
1873
|
+
* list.unshift(1);
|
|
1874
|
+
* console.log([...list]); // [1, 2, 3];
|
|
1875
|
+
*/
|
|
1518
1876
|
unshift(elementOrNode) {
|
|
1519
1877
|
const newNode = this._ensureNode(elementOrNode);
|
|
1520
1878
|
if (!this.head) {
|
|
@@ -1558,11 +1916,27 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1558
1916
|
return ans;
|
|
1559
1917
|
}
|
|
1560
1918
|
/**
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1919
|
+
* Get the element at a given index.
|
|
1920
|
+
* @remarks Time O(N), Space O(1)
|
|
1921
|
+
* @param index - Zero-based index.
|
|
1922
|
+
* @returns Element or undefined.
|
|
1923
|
+
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
|
|
1931
|
+
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
* @example
|
|
1935
|
+
* // Access by index
|
|
1936
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
1937
|
+
* console.log(list.at(1)); // 'b';
|
|
1938
|
+
* console.log(list.at(2)); // 'c';
|
|
1939
|
+
*/
|
|
1566
1940
|
at(index) {
|
|
1567
1941
|
if (index < 0 || index >= this._length) return void 0;
|
|
1568
1942
|
let current = this.head;
|
|
@@ -1570,11 +1944,23 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1570
1944
|
return current == null ? void 0 : current.value;
|
|
1571
1945
|
}
|
|
1572
1946
|
/**
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1947
|
+
* Get the node reference at a given index.
|
|
1948
|
+
* @remarks Time O(N), Space O(1)
|
|
1949
|
+
* @param index - Zero-based index.
|
|
1950
|
+
* @returns Node or undefined.
|
|
1951
|
+
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
|
|
1955
|
+
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
|
|
1959
|
+
* @example
|
|
1960
|
+
* // Get node at index
|
|
1961
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
1962
|
+
* console.log(list.getNodeAt(1)?.value); // 'b';
|
|
1963
|
+
*/
|
|
1578
1964
|
getNodeAt(index) {
|
|
1579
1965
|
if (index < 0 || index >= this._length) return void 0;
|
|
1580
1966
|
let current = this.head;
|
|
@@ -1613,12 +1999,25 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1613
1999
|
return void 0;
|
|
1614
2000
|
}
|
|
1615
2001
|
/**
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
2002
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
2003
|
+
* @remarks Time O(N), Space O(1)
|
|
2004
|
+
* @param index - Zero-based index.
|
|
2005
|
+
* @param newElementOrNode - Element or node to insert.
|
|
2006
|
+
* @returns True if inserted.
|
|
2007
|
+
|
|
2008
|
+
|
|
2009
|
+
|
|
2010
|
+
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
|
|
2014
|
+
|
|
2015
|
+
* @example
|
|
2016
|
+
* // Insert at position
|
|
2017
|
+
* const list = new DoublyLinkedList<number>([1, 3]);
|
|
2018
|
+
* list.addAt(1, 2);
|
|
2019
|
+
* console.log(list.toArray()); // [1, 2, 3];
|
|
2020
|
+
*/
|
|
1622
2021
|
addAt(index, newElementOrNode) {
|
|
1623
2022
|
if (index < 0 || index > this._length) return false;
|
|
1624
2023
|
if (index === 0) return this.unshift(newElementOrNode);
|
|
@@ -1685,11 +2084,24 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1685
2084
|
return true;
|
|
1686
2085
|
}
|
|
1687
2086
|
/**
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
2087
|
+
* Delete the element at an index.
|
|
2088
|
+
* @remarks Time O(N), Space O(1)
|
|
2089
|
+
* @param index - Zero-based index.
|
|
2090
|
+
* @returns Removed element or undefined.
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
|
|
2099
|
+
* @example
|
|
2100
|
+
* // Remove by index
|
|
2101
|
+
* const list = new DoublyLinkedList<string>(['a', 'b', 'c']);
|
|
2102
|
+
* list.deleteAt(1);
|
|
2103
|
+
* console.log(list.toArray()); // ['a', 'c'];
|
|
2104
|
+
*/
|
|
1693
2105
|
deleteAt(index) {
|
|
1694
2106
|
if (index < 0 || index >= this._length) return;
|
|
1695
2107
|
if (index === 0) return this.shift();
|
|
@@ -1703,11 +2115,24 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1703
2115
|
return removedNode.value;
|
|
1704
2116
|
}
|
|
1705
2117
|
/**
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
2118
|
+
* Delete the first match by value/node.
|
|
2119
|
+
* @remarks Time O(N), Space O(1)
|
|
2120
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
2121
|
+
* @returns True if removed.
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
* @example
|
|
2131
|
+
* // Remove first occurrence
|
|
2132
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 2]);
|
|
2133
|
+
* list.delete(2);
|
|
2134
|
+
* console.log(list.toArray()); // [1, 3, 2];
|
|
2135
|
+
*/
|
|
1711
2136
|
delete(elementOrNode) {
|
|
1712
2137
|
const node = this.getNode(elementOrNode);
|
|
1713
2138
|
if (!node) return false;
|
|
@@ -1723,29 +2148,68 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1723
2148
|
return true;
|
|
1724
2149
|
}
|
|
1725
2150
|
/**
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
2151
|
+
* Check whether the list is empty.
|
|
2152
|
+
* @remarks Time O(1), Space O(1)
|
|
2153
|
+
* @returns True if length is 0.
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
|
|
2157
|
+
|
|
2158
|
+
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
* @example
|
|
2164
|
+
* // Check empty
|
|
2165
|
+
* console.log(new DoublyLinkedList().isEmpty()); // true;
|
|
2166
|
+
*/
|
|
1730
2167
|
isEmpty() {
|
|
1731
2168
|
return this._length === 0;
|
|
1732
2169
|
}
|
|
1733
2170
|
/**
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
2171
|
+
* Remove all nodes and reset length.
|
|
2172
|
+
* @remarks Time O(N), Space O(1)
|
|
2173
|
+
* @returns void
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
* @example
|
|
2184
|
+
* // Remove all
|
|
2185
|
+
* const list = new DoublyLinkedList<number>([1, 2]);
|
|
2186
|
+
* list.clear();
|
|
2187
|
+
* console.log(list.isEmpty()); // true;
|
|
2188
|
+
*/
|
|
1738
2189
|
clear() {
|
|
1739
2190
|
this._head = void 0;
|
|
1740
2191
|
this._tail = void 0;
|
|
1741
2192
|
this._length = 0;
|
|
1742
2193
|
}
|
|
1743
2194
|
/**
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
2195
|
+
* Find the first value matching a predicate scanning forward.
|
|
2196
|
+
* @remarks Time O(N), Space O(1)
|
|
2197
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2198
|
+
* @returns Matched value or undefined.
|
|
2199
|
+
|
|
2200
|
+
|
|
2201
|
+
|
|
2202
|
+
|
|
2203
|
+
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
* @example
|
|
2208
|
+
* // Search with predicate
|
|
2209
|
+
* const list = new DoublyLinkedList<number>([10, 20, 30]);
|
|
2210
|
+
* const found = list.search(node => node.value > 15);
|
|
2211
|
+
* console.log(found); // 20;
|
|
2212
|
+
*/
|
|
1749
2213
|
search(elementNodeOrPredicate) {
|
|
1750
2214
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1751
2215
|
let current = this.head;
|
|
@@ -1756,11 +2220,25 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1756
2220
|
return void 0;
|
|
1757
2221
|
}
|
|
1758
2222
|
/**
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
2223
|
+
* Find the first value matching a predicate scanning backward.
|
|
2224
|
+
* @remarks Time O(N), Space O(1)
|
|
2225
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
2226
|
+
* @returns Matched value or undefined.
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
|
|
2233
|
+
|
|
2234
|
+
|
|
2235
|
+
* @example
|
|
2236
|
+
* // Find value scanning from tail
|
|
2237
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4]);
|
|
2238
|
+
* // getBackward scans from tail to head, returns first match
|
|
2239
|
+
* const found = list.getBackward(node => node.value < 4);
|
|
2240
|
+
* console.log(found); // 3;
|
|
2241
|
+
*/
|
|
1764
2242
|
getBackward(elementNodeOrPredicate) {
|
|
1765
2243
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
1766
2244
|
let current = this.tail;
|
|
@@ -1771,10 +2249,26 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1771
2249
|
return void 0;
|
|
1772
2250
|
}
|
|
1773
2251
|
/**
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
2252
|
+
* Reverse the list in place.
|
|
2253
|
+
* @remarks Time O(N), Space O(1)
|
|
2254
|
+
* @returns This list.
|
|
2255
|
+
|
|
2256
|
+
|
|
2257
|
+
|
|
2258
|
+
|
|
2259
|
+
|
|
2260
|
+
|
|
2261
|
+
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
* @example
|
|
2267
|
+
* // Reverse in-place
|
|
2268
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2269
|
+
* list.reverse();
|
|
2270
|
+
* console.log([...list]); // [3, 2, 1];
|
|
2271
|
+
*/
|
|
1778
2272
|
reverse() {
|
|
1779
2273
|
let current = this.head;
|
|
1780
2274
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1796,22 +2290,53 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1796
2290
|
return this;
|
|
1797
2291
|
}
|
|
1798
2292
|
/**
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
2293
|
+
* Deep clone this list (values are copied by reference).
|
|
2294
|
+
* @remarks Time O(N), Space O(N)
|
|
2295
|
+
* @returns A new list with the same element sequence.
|
|
2296
|
+
|
|
2297
|
+
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
|
|
2301
|
+
|
|
2302
|
+
|
|
2303
|
+
|
|
2304
|
+
|
|
2305
|
+
* @example
|
|
2306
|
+
* // Deep copy
|
|
2307
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3]);
|
|
2308
|
+
* const copy = list.clone();
|
|
2309
|
+
* copy.pop();
|
|
2310
|
+
* console.log(list.length); // 3;
|
|
2311
|
+
*/
|
|
1803
2312
|
clone() {
|
|
1804
2313
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1805
2314
|
for (const v of this) out.push(v);
|
|
1806
2315
|
return out;
|
|
1807
2316
|
}
|
|
1808
2317
|
/**
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2318
|
+
* Filter values into a new list of the same class.
|
|
2319
|
+
* @remarks Time O(N), Space O(N)
|
|
2320
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
2321
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2322
|
+
* @returns A new list with kept values.
|
|
2323
|
+
|
|
2324
|
+
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
|
|
2330
|
+
|
|
2331
|
+
|
|
2332
|
+
|
|
2333
|
+
|
|
2334
|
+
* @example
|
|
2335
|
+
* // Filter elements
|
|
2336
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
2337
|
+
* const evens = list.filter(n => n % 2 === 0);
|
|
2338
|
+
* console.log([...evens]); // [2, 4];
|
|
2339
|
+
*/
|
|
1815
2340
|
filter(callback, thisArg) {
|
|
1816
2341
|
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1817
2342
|
let index = 0;
|
|
@@ -1835,15 +2360,40 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1835
2360
|
return out;
|
|
1836
2361
|
}
|
|
1837
2362
|
/**
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
2363
|
+
* Map values into a new list (possibly different element type).
|
|
2364
|
+
* @remarks Time O(N), Space O(N)
|
|
2365
|
+
* @template EM
|
|
2366
|
+
* @template RM
|
|
2367
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
2368
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
2369
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
2370
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
2371
|
+
|
|
2372
|
+
|
|
2373
|
+
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
|
|
2377
|
+
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
|
|
2382
|
+
* @example
|
|
2383
|
+
* // DoublyLinkedList for...of iteration and map operation
|
|
2384
|
+
* const list = new DoublyLinkedList<number>([1, 2, 3, 4, 5]);
|
|
2385
|
+
*
|
|
2386
|
+
* // Iterate through list
|
|
2387
|
+
* const doubled = list.map(value => value * 2);
|
|
2388
|
+
* console.log(doubled.length); // 5;
|
|
2389
|
+
*
|
|
2390
|
+
* // Use for...of loop
|
|
2391
|
+
* const result: number[] = [];
|
|
2392
|
+
* for (const item of list) {
|
|
2393
|
+
* result.push(item);
|
|
2394
|
+
* }
|
|
2395
|
+
* console.log(result); // [1, 2, 3, 4, 5];
|
|
2396
|
+
*/
|
|
1847
2397
|
map(callback, options, thisArg) {
|
|
1848
2398
|
const out = this._createLike([], { ...options != null ? options : {}, maxLen: this._maxLen });
|
|
1849
2399
|
let index = 0;
|
|
@@ -1934,6 +2484,235 @@ var _DoublyLinkedList = class _DoublyLinkedList extends LinearLinkedBase {
|
|
|
1934
2484
|
__name(_DoublyLinkedList, "DoublyLinkedList");
|
|
1935
2485
|
var DoublyLinkedList = _DoublyLinkedList;
|
|
1936
2486
|
|
|
2487
|
+
// src/common/error.ts
|
|
2488
|
+
var ERR = {
|
|
2489
|
+
// Range / index
|
|
2490
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
2491
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
2492
|
+
// Type / argument
|
|
2493
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
2494
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
2495
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
2496
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
2497
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
2498
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
2499
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
2500
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
2501
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
2502
|
+
// State / operation
|
|
2503
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
2504
|
+
// Matrix
|
|
2505
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
2506
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
2507
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
2508
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
2509
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
2510
|
+
};
|
|
2511
|
+
|
|
2512
|
+
// src/common/index.ts
|
|
2513
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
2514
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
2515
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
2516
|
+
return DFSOperation2;
|
|
2517
|
+
})(DFSOperation || {});
|
|
2518
|
+
var _Range = class _Range {
|
|
2519
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
2520
|
+
this.low = low;
|
|
2521
|
+
this.high = high;
|
|
2522
|
+
this.includeLow = includeLow;
|
|
2523
|
+
this.includeHigh = includeHigh;
|
|
2524
|
+
}
|
|
2525
|
+
// Determine whether a key is within the range
|
|
2526
|
+
isInRange(key, comparator) {
|
|
2527
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
2528
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
2529
|
+
return lowCheck && highCheck;
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
__name(_Range, "Range");
|
|
2533
|
+
var Range = _Range;
|
|
2534
|
+
|
|
2535
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
2536
|
+
var _IterableEntryBase = class _IterableEntryBase {
|
|
2537
|
+
/**
|
|
2538
|
+
* Default iterator yielding `[key, value]` entries.
|
|
2539
|
+
* @returns Iterator of `[K, V]`.
|
|
2540
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
2541
|
+
*/
|
|
2542
|
+
*[Symbol.iterator](...args) {
|
|
2543
|
+
yield* this._getIterator(...args);
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
2547
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
2548
|
+
* @remarks Time O(n), Space O(1)
|
|
2549
|
+
*/
|
|
2550
|
+
*entries() {
|
|
2551
|
+
for (const item of this) {
|
|
2552
|
+
yield item;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
/**
|
|
2556
|
+
* Iterate over keys only.
|
|
2557
|
+
* @returns Iterator of keys.
|
|
2558
|
+
* @remarks Time O(n), Space O(1)
|
|
2559
|
+
*/
|
|
2560
|
+
*keys() {
|
|
2561
|
+
for (const item of this) {
|
|
2562
|
+
yield item[0];
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
/**
|
|
2566
|
+
* Iterate over values only.
|
|
2567
|
+
* @returns Iterator of values.
|
|
2568
|
+
* @remarks Time O(n), Space O(1)
|
|
2569
|
+
*/
|
|
2570
|
+
*values() {
|
|
2571
|
+
for (const item of this) {
|
|
2572
|
+
yield item[1];
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Test whether all entries satisfy the predicate.
|
|
2577
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
2578
|
+
* @param thisArg - Optional `this` for callback.
|
|
2579
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
2580
|
+
* @remarks Time O(n), Space O(1)
|
|
2581
|
+
*/
|
|
2582
|
+
every(predicate, thisArg) {
|
|
2583
|
+
let index = 0;
|
|
2584
|
+
for (const item of this) {
|
|
2585
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
2586
|
+
return false;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return true;
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Test whether any entry satisfies the predicate.
|
|
2593
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
2594
|
+
* @param thisArg - Optional `this` for callback.
|
|
2595
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
2596
|
+
* @remarks Time O(n), Space O(1)
|
|
2597
|
+
*/
|
|
2598
|
+
some(predicate, thisArg) {
|
|
2599
|
+
let index = 0;
|
|
2600
|
+
for (const item of this) {
|
|
2601
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
2602
|
+
return true;
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
return false;
|
|
2606
|
+
}
|
|
2607
|
+
/**
|
|
2608
|
+
* Visit each entry, left-to-right.
|
|
2609
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
2610
|
+
* @param thisArg - Optional `this` for callback.
|
|
2611
|
+
* @remarks Time O(n), Space O(1)
|
|
2612
|
+
*/
|
|
2613
|
+
forEach(callbackfn, thisArg) {
|
|
2614
|
+
let index = 0;
|
|
2615
|
+
for (const item of this) {
|
|
2616
|
+
const [key, value] = item;
|
|
2617
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* Find the first entry that matches a predicate.
|
|
2622
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
2623
|
+
* @param thisArg - Optional `this` for callback.
|
|
2624
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
2625
|
+
* @remarks Time O(n), Space O(1)
|
|
2626
|
+
*/
|
|
2627
|
+
find(callbackfn, thisArg) {
|
|
2628
|
+
let index = 0;
|
|
2629
|
+
for (const item of this) {
|
|
2630
|
+
const [key, value] = item;
|
|
2631
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
2632
|
+
}
|
|
2633
|
+
return;
|
|
2634
|
+
}
|
|
2635
|
+
/**
|
|
2636
|
+
* Whether the given key exists.
|
|
2637
|
+
* @param key - Key to test.
|
|
2638
|
+
* @returns `true` if found; otherwise `false`.
|
|
2639
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
2640
|
+
*/
|
|
2641
|
+
has(key) {
|
|
2642
|
+
for (const item of this) {
|
|
2643
|
+
const [itemKey] = item;
|
|
2644
|
+
if (itemKey === key) return true;
|
|
2645
|
+
}
|
|
2646
|
+
return false;
|
|
2647
|
+
}
|
|
2648
|
+
/**
|
|
2649
|
+
* Whether there exists an entry with the given value.
|
|
2650
|
+
* @param value - Value to test.
|
|
2651
|
+
* @returns `true` if found; otherwise `false`.
|
|
2652
|
+
* @remarks Time O(n), Space O(1)
|
|
2653
|
+
*/
|
|
2654
|
+
hasValue(value) {
|
|
2655
|
+
for (const [, elementValue] of this) {
|
|
2656
|
+
if (elementValue === value) return true;
|
|
2657
|
+
}
|
|
2658
|
+
return false;
|
|
2659
|
+
}
|
|
2660
|
+
/**
|
|
2661
|
+
* Get the value under a key.
|
|
2662
|
+
* @param key - Key to look up.
|
|
2663
|
+
* @returns Value or `undefined`.
|
|
2664
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
2665
|
+
*/
|
|
2666
|
+
get(key) {
|
|
2667
|
+
for (const item of this) {
|
|
2668
|
+
const [itemKey, value] = item;
|
|
2669
|
+
if (itemKey === key) return value;
|
|
2670
|
+
}
|
|
2671
|
+
return;
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Reduce entries into a single accumulator.
|
|
2675
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
2676
|
+
* @param initialValue - Initial accumulator.
|
|
2677
|
+
* @returns Final accumulator.
|
|
2678
|
+
* @remarks Time O(n), Space O(1)
|
|
2679
|
+
*/
|
|
2680
|
+
reduce(callbackfn, initialValue) {
|
|
2681
|
+
let accumulator = initialValue;
|
|
2682
|
+
let index = 0;
|
|
2683
|
+
for (const item of this) {
|
|
2684
|
+
const [key, value] = item;
|
|
2685
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
2686
|
+
}
|
|
2687
|
+
return accumulator;
|
|
2688
|
+
}
|
|
2689
|
+
/**
|
|
2690
|
+
* Converts data structure to `[key, value]` pairs.
|
|
2691
|
+
* @returns Array of entries.
|
|
2692
|
+
* @remarks Time O(n), Space O(n)
|
|
2693
|
+
*/
|
|
2694
|
+
toArray() {
|
|
2695
|
+
return [...this];
|
|
2696
|
+
}
|
|
2697
|
+
/**
|
|
2698
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
2699
|
+
* @returns Array of entries (default) or a string.
|
|
2700
|
+
* @remarks Time O(n), Space O(n)
|
|
2701
|
+
*/
|
|
2702
|
+
toVisual() {
|
|
2703
|
+
return [...this];
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Print a human-friendly representation to the console.
|
|
2707
|
+
* @remarks Time O(n), Space O(n)
|
|
2708
|
+
*/
|
|
2709
|
+
print() {
|
|
2710
|
+
console.log(this.toVisual());
|
|
2711
|
+
}
|
|
2712
|
+
};
|
|
2713
|
+
__name(_IterableEntryBase, "IterableEntryBase");
|
|
2714
|
+
var IterableEntryBase = _IterableEntryBase;
|
|
2715
|
+
|
|
1937
2716
|
// src/data-structures/linked-list/skip-linked-list.ts
|
|
1938
2717
|
var _SkipListNode = class _SkipListNode {
|
|
1939
2718
|
constructor(key, value, level) {
|
|
@@ -1942,31 +2721,69 @@ var _SkipListNode = class _SkipListNode {
|
|
|
1942
2721
|
__publicField(this, "forward");
|
|
1943
2722
|
this.key = key;
|
|
1944
2723
|
this.value = value;
|
|
1945
|
-
this.forward = new Array(level);
|
|
2724
|
+
this.forward = new Array(level).fill(void 0);
|
|
1946
2725
|
}
|
|
1947
2726
|
};
|
|
1948
2727
|
__name(_SkipListNode, "SkipListNode");
|
|
1949
2728
|
var SkipListNode = _SkipListNode;
|
|
1950
|
-
var
|
|
1951
|
-
|
|
1952
|
-
|
|
2729
|
+
var _comparator, _isDefaultComparator;
|
|
2730
|
+
var _SkipList = class _SkipList extends IterableEntryBase {
|
|
2731
|
+
constructor(entries = [], options = {}) {
|
|
2732
|
+
super();
|
|
2733
|
+
__privateAdd(this, _comparator);
|
|
2734
|
+
__privateAdd(this, _isDefaultComparator);
|
|
2735
|
+
// ─── Internal state ──────────────────────────────────────────
|
|
2736
|
+
__publicField(this, "_head");
|
|
1953
2737
|
__publicField(this, "_level", 0);
|
|
2738
|
+
__publicField(this, "_size", 0);
|
|
1954
2739
|
__publicField(this, "_maxLevel", 16);
|
|
1955
2740
|
__publicField(this, "_probability", 0.5);
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
2741
|
+
const { comparator, toEntryFn, maxLevel, probability } = options;
|
|
2742
|
+
if (typeof maxLevel === "number" && maxLevel > 0) this._maxLevel = maxLevel;
|
|
2743
|
+
if (typeof probability === "number" && probability > 0 && probability < 1) this._probability = probability;
|
|
2744
|
+
__privateSet(this, _isDefaultComparator, comparator === void 0);
|
|
2745
|
+
__privateSet(this, _comparator, comparator != null ? comparator : _SkipList.createDefaultComparator());
|
|
2746
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
2747
|
+
for (const item of entries) {
|
|
2748
|
+
let k;
|
|
2749
|
+
let v;
|
|
2750
|
+
if (toEntryFn) {
|
|
2751
|
+
[k, v] = toEntryFn(item);
|
|
2752
|
+
} else {
|
|
2753
|
+
if (!Array.isArray(item) || item.length < 2) {
|
|
2754
|
+
throw new TypeError(ERR.invalidEntry("SkipList"));
|
|
2755
|
+
}
|
|
2756
|
+
[k, v] = item;
|
|
2757
|
+
}
|
|
2758
|
+
this.set(k, v);
|
|
1963
2759
|
}
|
|
1964
2760
|
}
|
|
1965
|
-
|
|
1966
|
-
|
|
2761
|
+
/**
|
|
2762
|
+
* Creates a default comparator supporting number, string, Date, and bigint.
|
|
2763
|
+
*/
|
|
2764
|
+
static createDefaultComparator() {
|
|
2765
|
+
return (a, b) => {
|
|
2766
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
2767
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("SkipList"));
|
|
2768
|
+
return a - b;
|
|
2769
|
+
}
|
|
2770
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
2771
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
2772
|
+
}
|
|
2773
|
+
if (a instanceof Date && b instanceof Date) {
|
|
2774
|
+
const ta = a.getTime(), tb = b.getTime();
|
|
2775
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("SkipList"));
|
|
2776
|
+
return ta - tb;
|
|
2777
|
+
}
|
|
2778
|
+
if (typeof a === "bigint" && typeof b === "bigint") {
|
|
2779
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
2780
|
+
}
|
|
2781
|
+
throw new TypeError(ERR.comparatorRequired("SkipList"));
|
|
2782
|
+
};
|
|
1967
2783
|
}
|
|
1968
|
-
|
|
1969
|
-
|
|
2784
|
+
// ─── Size & lifecycle ────────────────────────────────────────
|
|
2785
|
+
get size() {
|
|
2786
|
+
return this._size;
|
|
1970
2787
|
}
|
|
1971
2788
|
get maxLevel() {
|
|
1972
2789
|
return this._maxLevel;
|
|
@@ -1974,133 +2791,594 @@ var _SkipList = class _SkipList {
|
|
|
1974
2791
|
get probability() {
|
|
1975
2792
|
return this._probability;
|
|
1976
2793
|
}
|
|
1977
|
-
get
|
|
1978
|
-
|
|
1979
|
-
|
|
2794
|
+
get comparator() {
|
|
2795
|
+
return __privateGet(this, _comparator);
|
|
2796
|
+
}
|
|
2797
|
+
/**
|
|
2798
|
+
* Check if empty
|
|
2799
|
+
|
|
2800
|
+
|
|
2801
|
+
|
|
2802
|
+
|
|
2803
|
+
|
|
2804
|
+
|
|
2805
|
+
|
|
2806
|
+
|
|
2807
|
+
* @example
|
|
2808
|
+
* // Check if empty
|
|
2809
|
+
* const sl = new SkipList<number, string>();
|
|
2810
|
+
* console.log(sl.isEmpty()); // true;
|
|
2811
|
+
*/
|
|
2812
|
+
isEmpty() {
|
|
2813
|
+
return this._size === 0;
|
|
2814
|
+
}
|
|
2815
|
+
/**
|
|
2816
|
+
* Remove all entries
|
|
2817
|
+
|
|
2818
|
+
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
|
|
2822
|
+
|
|
2823
|
+
|
|
2824
|
+
|
|
2825
|
+
* @example
|
|
2826
|
+
* // Remove all entries
|
|
2827
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
2828
|
+
* sl.clear();
|
|
2829
|
+
* console.log(sl.isEmpty()); // true;
|
|
2830
|
+
*/
|
|
2831
|
+
clear() {
|
|
2832
|
+
this._head = new SkipListNode(void 0, void 0, this._maxLevel);
|
|
2833
|
+
this._level = 0;
|
|
2834
|
+
this._size = 0;
|
|
2835
|
+
}
|
|
2836
|
+
/**
|
|
2837
|
+
* Create independent copy
|
|
2838
|
+
|
|
2839
|
+
|
|
2840
|
+
|
|
2841
|
+
|
|
2842
|
+
|
|
2843
|
+
|
|
2844
|
+
|
|
2845
|
+
|
|
2846
|
+
* @example
|
|
2847
|
+
* // Create independent copy
|
|
2848
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
2849
|
+
* const copy = sl.clone();
|
|
2850
|
+
* copy.delete(1);
|
|
2851
|
+
* console.log(sl.has(1)); // true;
|
|
2852
|
+
*/
|
|
2853
|
+
clone() {
|
|
2854
|
+
return new _SkipList(this, {
|
|
2855
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
2856
|
+
maxLevel: this._maxLevel,
|
|
2857
|
+
probability: this._probability
|
|
2858
|
+
});
|
|
2859
|
+
}
|
|
2860
|
+
// ─── Core CRUD ───────────────────────────────────────────────
|
|
2861
|
+
/**
|
|
2862
|
+
* Insert or update a key-value pair. Returns `this` for chaining.
|
|
2863
|
+
* Unique keys only — if key exists, value is updated in place.
|
|
2864
|
+
|
|
2865
|
+
|
|
2866
|
+
|
|
2867
|
+
|
|
2868
|
+
|
|
2869
|
+
|
|
2870
|
+
|
|
2871
|
+
|
|
2872
|
+
|
|
2873
|
+
|
|
2874
|
+
|
|
2875
|
+
* @example
|
|
2876
|
+
* // In-memory sorted key-value store
|
|
2877
|
+
* const store = new SkipList<number, string>();
|
|
2878
|
+
*
|
|
2879
|
+
* store.set(3, 'three');
|
|
2880
|
+
* store.set(1, 'one');
|
|
2881
|
+
* store.set(5, 'five');
|
|
2882
|
+
* store.set(2, 'two');
|
|
2883
|
+
*
|
|
2884
|
+
* console.log(store.get(3)); // 'three';
|
|
2885
|
+
* console.log(store.get(1)); // 'one';
|
|
2886
|
+
* console.log(store.get(5)); // 'five';
|
|
2887
|
+
*
|
|
2888
|
+
* // Update existing key
|
|
2889
|
+
* store.set(3, 'THREE');
|
|
2890
|
+
* console.log(store.get(3)); // 'THREE';
|
|
2891
|
+
*/
|
|
2892
|
+
set(key, value) {
|
|
2893
|
+
const cmp = __privateGet(this, _comparator);
|
|
2894
|
+
const update = this._findUpdate(key);
|
|
2895
|
+
const existing = update[0].forward[0];
|
|
2896
|
+
if (existing && cmp(existing.key, key) === 0) {
|
|
2897
|
+
existing.value = value;
|
|
2898
|
+
return this;
|
|
2899
|
+
}
|
|
2900
|
+
const newLevel = this._randomLevel();
|
|
2901
|
+
const newNode = new SkipListNode(key, value, newLevel);
|
|
2902
|
+
if (newLevel > this._level) {
|
|
2903
|
+
for (let i = this._level; i < newLevel; i++) {
|
|
2904
|
+
update[i] = this._head;
|
|
2905
|
+
}
|
|
2906
|
+
this._level = newLevel;
|
|
2907
|
+
}
|
|
2908
|
+
for (let i = 0; i < newLevel; i++) {
|
|
2909
|
+
newNode.forward[i] = update[i].forward[i];
|
|
2910
|
+
update[i].forward[i] = newNode;
|
|
2911
|
+
}
|
|
2912
|
+
this._size++;
|
|
2913
|
+
return this;
|
|
1980
2914
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
2915
|
+
/**
|
|
2916
|
+
* Get the value for a key, or `undefined` if not found.
|
|
2917
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
2918
|
+
|
|
2919
|
+
|
|
2920
|
+
|
|
2921
|
+
|
|
2922
|
+
|
|
2923
|
+
|
|
2924
|
+
|
|
2925
|
+
|
|
2926
|
+
|
|
2927
|
+
|
|
2928
|
+
|
|
2929
|
+
* @example
|
|
2930
|
+
* // Building a sorted index
|
|
2931
|
+
* type Product = { id: number; name: string; price: number };
|
|
2932
|
+
* const products: Product[] = [
|
|
2933
|
+
* { id: 1, name: 'Widget', price: 25 },
|
|
2934
|
+
* { id: 2, name: 'Gadget', price: 50 },
|
|
2935
|
+
* { id: 3, name: 'Doohickey', price: 15 }
|
|
2936
|
+
* ];
|
|
2937
|
+
*
|
|
2938
|
+
* const index = new SkipList<number, Product>(products as any, {
|
|
2939
|
+
* toEntryFn: (p: any) => [p.price, p]
|
|
2940
|
+
* });
|
|
2941
|
+
*
|
|
2942
|
+
* // Iterate in sorted order by price
|
|
2943
|
+
* const names = [...index.values()].map(p => p!.name);
|
|
2944
|
+
* console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
|
|
2945
|
+
*
|
|
2946
|
+
* // Range search: products between $20 and $60
|
|
2947
|
+
* const range = index.rangeSearch([20, 60]);
|
|
2948
|
+
* console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
|
|
2949
|
+
*/
|
|
2950
|
+
get(key) {
|
|
2951
|
+
const node = this._findNode(key);
|
|
2952
|
+
return node ? node.value : void 0;
|
|
2953
|
+
}
|
|
2954
|
+
/**
|
|
2955
|
+
* Check if a key exists.
|
|
2956
|
+
* Overrides base O(n) with O(log n) skip-list search.
|
|
2957
|
+
|
|
2958
|
+
|
|
2959
|
+
|
|
2960
|
+
|
|
2961
|
+
|
|
2962
|
+
|
|
2963
|
+
|
|
2964
|
+
|
|
2965
|
+
|
|
2966
|
+
|
|
2967
|
+
|
|
2968
|
+
* @example
|
|
2969
|
+
* // Check key existence
|
|
2970
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
|
|
2971
|
+
* console.log(sl.has(3)); // true;
|
|
2972
|
+
* console.log(sl.has(4)); // false;
|
|
2973
|
+
*/
|
|
2974
|
+
has(key) {
|
|
2975
|
+
return this._findNode(key) !== void 0;
|
|
2976
|
+
}
|
|
2977
|
+
/**
|
|
2978
|
+
* Delete a key. Returns `true` if the key was found and removed.
|
|
2979
|
+
|
|
2980
|
+
|
|
2981
|
+
|
|
2982
|
+
|
|
2983
|
+
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
|
|
2987
|
+
|
|
2988
|
+
|
|
2989
|
+
|
|
2990
|
+
* @example
|
|
2991
|
+
* // Fast lookup with deletion
|
|
2992
|
+
* const cache = new SkipList<string, number>();
|
|
2993
|
+
*
|
|
2994
|
+
* cache.set('alpha', 1);
|
|
2995
|
+
* cache.set('beta', 2);
|
|
2996
|
+
* cache.set('gamma', 3);
|
|
2997
|
+
*
|
|
2998
|
+
* console.log(cache.has('beta')); // true;
|
|
2999
|
+
* cache.delete('beta');
|
|
3000
|
+
* console.log(cache.has('beta')); // false;
|
|
3001
|
+
* console.log(cache.size); // 2;
|
|
3002
|
+
*/
|
|
3003
|
+
delete(key) {
|
|
3004
|
+
const cmp = __privateGet(this, _comparator);
|
|
3005
|
+
const update = this._findUpdate(key);
|
|
3006
|
+
const target = update[0].forward[0];
|
|
3007
|
+
if (!target || cmp(target.key, key) !== 0) return false;
|
|
3008
|
+
for (let i = 0; i < this._level; i++) {
|
|
3009
|
+
if (update[i].forward[i] !== target) break;
|
|
3010
|
+
update[i].forward[i] = target.forward[i];
|
|
3011
|
+
}
|
|
3012
|
+
while (this._level > 0 && !this._head.forward[this._level - 1]) {
|
|
3013
|
+
this._level--;
|
|
3014
|
+
}
|
|
3015
|
+
this._size--;
|
|
3016
|
+
return true;
|
|
3017
|
+
}
|
|
3018
|
+
// ─── Navigation ──────────────────────────────────────────────
|
|
3019
|
+
/**
|
|
3020
|
+
* Returns the first (smallest key) entry, or `undefined` if empty.
|
|
3021
|
+
|
|
3022
|
+
|
|
3023
|
+
|
|
3024
|
+
|
|
3025
|
+
|
|
3026
|
+
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
* @example
|
|
3033
|
+
* // Access the minimum entry
|
|
3034
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3035
|
+
* console.log(sl.first()); // [1, 'a'];
|
|
3036
|
+
*/
|
|
3037
|
+
first() {
|
|
3038
|
+
const node = this._head.forward[0];
|
|
3039
|
+
return node ? [node.key, node.value] : void 0;
|
|
3040
|
+
}
|
|
3041
|
+
/**
|
|
3042
|
+
* Returns the last (largest key) entry, or `undefined` if empty.
|
|
3043
|
+
|
|
3044
|
+
|
|
3045
|
+
|
|
3046
|
+
|
|
3047
|
+
|
|
3048
|
+
|
|
3049
|
+
|
|
3050
|
+
|
|
3051
|
+
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
* @example
|
|
3055
|
+
* // Access the maximum entry
|
|
3056
|
+
* const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
|
|
3057
|
+
* console.log(sl.last()); // [5, 'e'];
|
|
3058
|
+
*/
|
|
3059
|
+
last() {
|
|
3060
|
+
let current = this._head;
|
|
3061
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
1984
3062
|
while (current.forward[i]) {
|
|
1985
3063
|
current = current.forward[i];
|
|
1986
3064
|
}
|
|
1987
3065
|
}
|
|
1988
|
-
return current.value;
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
3066
|
+
return current === this._head ? void 0 : [current.key, current.value];
|
|
3067
|
+
}
|
|
3068
|
+
/**
|
|
3069
|
+
* Remove and return the first (smallest key) entry.
|
|
3070
|
+
|
|
3071
|
+
|
|
3072
|
+
|
|
3073
|
+
|
|
3074
|
+
|
|
3075
|
+
|
|
3076
|
+
|
|
3077
|
+
|
|
3078
|
+
* @example
|
|
3079
|
+
* // Remove and return smallest
|
|
3080
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3081
|
+
* console.log(sl.pollFirst()); // [1, 'a'];
|
|
3082
|
+
* console.log(sl.size); // 2;
|
|
3083
|
+
*/
|
|
3084
|
+
pollFirst() {
|
|
3085
|
+
const entry = this.first();
|
|
3086
|
+
if (!entry) return void 0;
|
|
3087
|
+
this.delete(entry[0]);
|
|
3088
|
+
return entry;
|
|
3089
|
+
}
|
|
3090
|
+
/**
|
|
3091
|
+
* Remove and return the last (largest key) entry.
|
|
3092
|
+
|
|
3093
|
+
|
|
3094
|
+
|
|
3095
|
+
|
|
3096
|
+
|
|
3097
|
+
|
|
3098
|
+
|
|
3099
|
+
|
|
3100
|
+
* @example
|
|
3101
|
+
* // Remove and return largest
|
|
3102
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3103
|
+
* console.log(sl.pollLast()); // [3, 'c'];
|
|
3104
|
+
* console.log(sl.size); // 2;
|
|
3105
|
+
*/
|
|
3106
|
+
pollLast() {
|
|
3107
|
+
const entry = this.last();
|
|
3108
|
+
if (!entry) return void 0;
|
|
3109
|
+
this.delete(entry[0]);
|
|
3110
|
+
return entry;
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Least entry ≥ key, or `undefined`.
|
|
3114
|
+
|
|
3115
|
+
|
|
3116
|
+
|
|
3117
|
+
|
|
3118
|
+
|
|
3119
|
+
|
|
3120
|
+
|
|
3121
|
+
|
|
3122
|
+
|
|
3123
|
+
|
|
3124
|
+
|
|
3125
|
+
* @example
|
|
3126
|
+
* // Least entry ≥ key
|
|
3127
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3128
|
+
* console.log(sl.ceiling(15)); // [20, 'b'];
|
|
3129
|
+
* console.log(sl.ceiling(20)); // [20, 'b'];
|
|
3130
|
+
*/
|
|
3131
|
+
ceiling(key) {
|
|
3132
|
+
const cmp = __privateGet(this, _comparator);
|
|
3133
|
+
let current = this._head;
|
|
3134
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3135
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
1996
3136
|
current = current.forward[i];
|
|
1997
3137
|
}
|
|
1998
|
-
update[i] = current;
|
|
1999
3138
|
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
3139
|
+
const node = current.forward[0];
|
|
3140
|
+
return node ? [node.key, node.value] : void 0;
|
|
3141
|
+
}
|
|
3142
|
+
/**
|
|
3143
|
+
* Greatest entry ≤ key, or `undefined`.
|
|
3144
|
+
|
|
3145
|
+
|
|
3146
|
+
|
|
3147
|
+
|
|
3148
|
+
|
|
3149
|
+
|
|
3150
|
+
|
|
3151
|
+
|
|
3152
|
+
|
|
3153
|
+
|
|
3154
|
+
|
|
3155
|
+
* @example
|
|
3156
|
+
* // Greatest entry ≤ key
|
|
3157
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3158
|
+
* console.log(sl.floor(25)); // [20, 'b'];
|
|
3159
|
+
* console.log(sl.floor(5)); // undefined;
|
|
3160
|
+
*/
|
|
3161
|
+
floor(key) {
|
|
3162
|
+
const cmp = __privateGet(this, _comparator);
|
|
3163
|
+
let current = this._head;
|
|
3164
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3165
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
3166
|
+
current = current.forward[i];
|
|
3167
|
+
}
|
|
2006
3168
|
}
|
|
3169
|
+
const result = current === this._head ? void 0 : current;
|
|
3170
|
+
if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
|
|
3171
|
+
return void 0;
|
|
2007
3172
|
}
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
3173
|
+
/**
|
|
3174
|
+
* Least entry strictly > key, or `undefined`.
|
|
3175
|
+
|
|
3176
|
+
|
|
3177
|
+
|
|
3178
|
+
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
|
|
3182
|
+
|
|
3183
|
+
* @example
|
|
3184
|
+
* // Strictly greater entry
|
|
3185
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3186
|
+
* console.log(sl.higher(15)); // [20, 'b'];
|
|
3187
|
+
* console.log(sl.higher(30)); // undefined;
|
|
3188
|
+
*/
|
|
3189
|
+
higher(key) {
|
|
3190
|
+
const cmp = __privateGet(this, _comparator);
|
|
3191
|
+
let current = this._head;
|
|
3192
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3193
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) <= 0) {
|
|
2012
3194
|
current = current.forward[i];
|
|
2013
3195
|
}
|
|
2014
3196
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
3197
|
+
const node = current.forward[0];
|
|
3198
|
+
return node ? [node.key, node.value] : void 0;
|
|
3199
|
+
}
|
|
3200
|
+
/**
|
|
3201
|
+
* Greatest entry strictly < key, or `undefined`.
|
|
3202
|
+
|
|
3203
|
+
|
|
3204
|
+
|
|
3205
|
+
|
|
3206
|
+
|
|
3207
|
+
|
|
3208
|
+
|
|
3209
|
+
|
|
3210
|
+
* @example
|
|
3211
|
+
* // Strictly less entry
|
|
3212
|
+
* const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
|
|
3213
|
+
* console.log(sl.lower(25)); // [20, 'b'];
|
|
3214
|
+
* console.log(sl.lower(10)); // undefined;
|
|
3215
|
+
*/
|
|
3216
|
+
lower(key) {
|
|
3217
|
+
const cmp = __privateGet(this, _comparator);
|
|
3218
|
+
let current = this._head;
|
|
3219
|
+
let result;
|
|
3220
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3221
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
3222
|
+
current = current.forward[i];
|
|
3223
|
+
}
|
|
3224
|
+
if (current !== this._head && cmp(current.key, key) < 0) {
|
|
3225
|
+
result = current;
|
|
3226
|
+
}
|
|
2018
3227
|
}
|
|
2019
|
-
return void 0;
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
3228
|
+
return result ? [result.key, result.value] : void 0;
|
|
3229
|
+
}
|
|
3230
|
+
/**
|
|
3231
|
+
* Returns entries within the given key range.
|
|
3232
|
+
|
|
3233
|
+
|
|
3234
|
+
|
|
3235
|
+
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
|
|
3239
|
+
|
|
3240
|
+
|
|
3241
|
+
|
|
3242
|
+
|
|
3243
|
+
* @example
|
|
3244
|
+
* // Find entries in a range
|
|
3245
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
|
|
3246
|
+
* const result = sl.rangeSearch([2, 4]);
|
|
3247
|
+
* console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
3248
|
+
*/
|
|
3249
|
+
rangeSearch(range, options = {}) {
|
|
3250
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
3251
|
+
const [low, high] = range;
|
|
3252
|
+
const cmp = __privateGet(this, _comparator);
|
|
3253
|
+
const out = [];
|
|
3254
|
+
let current = this._head;
|
|
3255
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3256
|
+
while (current.forward[i] && cmp(current.forward[i].key, low) < 0) {
|
|
2029
3257
|
current = current.forward[i];
|
|
2030
3258
|
}
|
|
2031
|
-
update[i] = current;
|
|
2032
3259
|
}
|
|
2033
3260
|
current = current.forward[0];
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
while (this.level > 0 && !this.head.forward[this.level - 1]) {
|
|
2042
|
-
this._level--;
|
|
3261
|
+
while (current) {
|
|
3262
|
+
const cmpHigh = cmp(current.key, high);
|
|
3263
|
+
if (cmpHigh > 0) break;
|
|
3264
|
+
if (cmpHigh === 0 && !highInclusive) break;
|
|
3265
|
+
const cmpLow = cmp(current.key, low);
|
|
3266
|
+
if (cmpLow > 0 || cmpLow === 0 && lowInclusive) {
|
|
3267
|
+
out.push([current.key, current.value]);
|
|
2043
3268
|
}
|
|
2044
|
-
|
|
3269
|
+
current = current.forward[0];
|
|
2045
3270
|
}
|
|
2046
|
-
return
|
|
3271
|
+
return out;
|
|
2047
3272
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
3273
|
+
// ─── Functional (overrides) ──────────────────────────────────
|
|
3274
|
+
/**
|
|
3275
|
+
* Creates a new SkipList with entries transformed by callback.
|
|
3276
|
+
|
|
3277
|
+
|
|
3278
|
+
|
|
3279
|
+
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
|
|
3284
|
+
* @example
|
|
3285
|
+
* // Transform entries
|
|
3286
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
|
|
3287
|
+
* const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
|
|
3288
|
+
* console.log([...mapped.values()]); // ['A', 'B'];
|
|
3289
|
+
*/
|
|
3290
|
+
map(callback, options) {
|
|
3291
|
+
const out = new _SkipList([], options != null ? options : {});
|
|
3292
|
+
let i = 0;
|
|
3293
|
+
for (const [k, v] of this) {
|
|
3294
|
+
const [nk, nv] = callback(v, k, i++, this);
|
|
3295
|
+
out.set(nk, nv);
|
|
3296
|
+
}
|
|
3297
|
+
return out;
|
|
3298
|
+
}
|
|
3299
|
+
/**
|
|
3300
|
+
* Creates a new SkipList with entries that pass the predicate.
|
|
3301
|
+
|
|
3302
|
+
|
|
3303
|
+
|
|
3304
|
+
|
|
3305
|
+
|
|
3306
|
+
|
|
3307
|
+
|
|
3308
|
+
|
|
3309
|
+
* @example
|
|
3310
|
+
* // Filter entries
|
|
3311
|
+
* const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3312
|
+
* const result = sl.filter((v, k) => k > 1);
|
|
3313
|
+
* console.log(result.size); // 2;
|
|
3314
|
+
*/
|
|
3315
|
+
filter(callbackfn, thisArg) {
|
|
3316
|
+
const out = new _SkipList([], {
|
|
3317
|
+
comparator: __privateGet(this, _isDefaultComparator) ? void 0 : __privateGet(this, _comparator),
|
|
3318
|
+
maxLevel: this._maxLevel,
|
|
3319
|
+
probability: this._probability
|
|
3320
|
+
});
|
|
3321
|
+
let i = 0;
|
|
3322
|
+
for (const [k, v] of this) {
|
|
3323
|
+
const ok = callbackfn.call(thisArg, v, k, i++, this);
|
|
3324
|
+
if (ok) out.set(k, v);
|
|
3325
|
+
}
|
|
3326
|
+
return out;
|
|
3327
|
+
}
|
|
3328
|
+
// ─── Iterator (required by IterableEntryBase) ────────────────
|
|
3329
|
+
_getIterator() {
|
|
3330
|
+
const head = this._head;
|
|
3331
|
+
return (function* () {
|
|
3332
|
+
let node = head.forward[0];
|
|
3333
|
+
while (node) {
|
|
3334
|
+
yield [node.key, node.value];
|
|
3335
|
+
node = node.forward[0];
|
|
3336
|
+
}
|
|
3337
|
+
})();
|
|
3338
|
+
}
|
|
3339
|
+
// ─── Internal helpers ────────────────────────────────────────
|
|
3340
|
+
/**
|
|
3341
|
+
* Finds the update array (predecessors at each level) for a given key.
|
|
3342
|
+
*/
|
|
3343
|
+
_findUpdate(key) {
|
|
3344
|
+
const cmp = __privateGet(this, _comparator);
|
|
3345
|
+
const update = new Array(this._maxLevel).fill(this._head);
|
|
3346
|
+
let current = this._head;
|
|
3347
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3348
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2052
3349
|
current = current.forward[i];
|
|
2053
3350
|
}
|
|
3351
|
+
update[i] = current;
|
|
2054
3352
|
}
|
|
2055
|
-
|
|
2056
|
-
return nextNode ? nextNode.value : void 0;
|
|
3353
|
+
return update;
|
|
2057
3354
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
3355
|
+
/**
|
|
3356
|
+
* Finds the node for a given key, or undefined.
|
|
3357
|
+
*/
|
|
3358
|
+
_findNode(key) {
|
|
3359
|
+
const cmp = __privateGet(this, _comparator);
|
|
3360
|
+
let current = this._head;
|
|
3361
|
+
for (let i = this._level - 1; i >= 0; i--) {
|
|
3362
|
+
while (current.forward[i] && cmp(current.forward[i].key, key) < 0) {
|
|
2063
3363
|
current = current.forward[i];
|
|
2064
3364
|
}
|
|
2065
|
-
if (current.key < key) {
|
|
2066
|
-
lastLess = current;
|
|
2067
|
-
}
|
|
2068
3365
|
}
|
|
2069
|
-
|
|
3366
|
+
const candidate = current.forward[0];
|
|
3367
|
+
if (candidate && cmp(candidate.key, key) === 0) return candidate;
|
|
3368
|
+
return void 0;
|
|
2070
3369
|
}
|
|
2071
3370
|
_randomLevel() {
|
|
2072
3371
|
let level = 1;
|
|
2073
|
-
while (Math.random() < this.
|
|
3372
|
+
while (Math.random() < this._probability && level < this._maxLevel) {
|
|
2074
3373
|
level++;
|
|
2075
3374
|
}
|
|
2076
3375
|
return level;
|
|
2077
3376
|
}
|
|
2078
3377
|
};
|
|
3378
|
+
_comparator = new WeakMap();
|
|
3379
|
+
_isDefaultComparator = new WeakMap();
|
|
2079
3380
|
__name(_SkipList, "SkipList");
|
|
2080
3381
|
var SkipList = _SkipList;
|
|
2081
|
-
|
|
2082
|
-
// src/common/index.ts
|
|
2083
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
2084
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
2085
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
2086
|
-
return DFSOperation2;
|
|
2087
|
-
})(DFSOperation || {});
|
|
2088
|
-
var _Range = class _Range {
|
|
2089
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
2090
|
-
this.low = low;
|
|
2091
|
-
this.high = high;
|
|
2092
|
-
this.includeLow = includeLow;
|
|
2093
|
-
this.includeHigh = includeHigh;
|
|
2094
|
-
}
|
|
2095
|
-
// Determine whether a key is within the range
|
|
2096
|
-
isInRange(key, comparator) {
|
|
2097
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
2098
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
2099
|
-
return lowCheck && highCheck;
|
|
2100
|
-
}
|
|
2101
|
-
};
|
|
2102
|
-
__name(_Range, "Range");
|
|
2103
|
-
var Range = _Range;
|
|
2104
3382
|
/**
|
|
2105
3383
|
* data-structure-typed
|
|
2106
3384
|
*
|
|
@@ -2109,6 +3387,6 @@ var Range = _Range;
|
|
|
2109
3387
|
* @license MIT License
|
|
2110
3388
|
*/
|
|
2111
3389
|
|
|
2112
|
-
export { DFSOperation, DoublyLinkedList, DoublyLinkedListNode, Range, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode };
|
|
3390
|
+
export { DFSOperation, DoublyLinkedList, DoublyLinkedListNode, ERR, Range, SinglyLinkedList, SinglyLinkedListNode, SkipList, SkipListNode };
|
|
2113
3391
|
//# sourceMappingURL=index.mjs.map
|
|
2114
3392
|
//# sourceMappingURL=index.mjs.map
|