data-structure-typed 0.8.6
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/.idea/data-structure-typed.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +2 -0
- package/dist/data-structures/binary-tree/aa-tree.js +6 -0
- package/dist/data-structures/binary-tree/avl-tree.js +231 -0
- package/dist/data-structures/binary-tree/b-tree.js +6 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +31 -0
- package/dist/data-structures/binary-tree/binary-tree.js +992 -0
- package/dist/data-structures/binary-tree/bst.js +431 -0
- package/dist/data-structures/binary-tree/index.js +20 -0
- package/dist/data-structures/binary-tree/rb-tree.js +6 -0
- package/dist/data-structures/binary-tree/segment-tree.js +151 -0
- package/dist/data-structures/binary-tree/splay-tree.js +6 -0
- package/dist/data-structures/binary-tree/tree-multiset.js +16 -0
- package/dist/data-structures/binary-tree/two-three-tree.js +6 -0
- package/dist/data-structures/graph/abstract-graph.js +648 -0
- package/dist/data-structures/graph/directed-graph.js +268 -0
- package/dist/data-structures/graph/index.js +19 -0
- package/dist/data-structures/graph/undirected-graph.js +142 -0
- package/dist/data-structures/hash/coordinate-map.js +24 -0
- package/dist/data-structures/hash/coordinate-set.js +21 -0
- package/dist/data-structures/hash/hash-table.js +2 -0
- package/dist/data-structures/hash/index.js +17 -0
- package/dist/data-structures/hash/pair.js +2 -0
- package/dist/data-structures/hash/tree-map.js +2 -0
- package/dist/data-structures/hash/tree-set.js +2 -0
- package/dist/data-structures/heap/heap.js +114 -0
- package/dist/data-structures/heap/index.js +19 -0
- package/dist/data-structures/heap/max-heap.js +22 -0
- package/dist/data-structures/heap/min-heap.js +22 -0
- package/dist/data-structures/index.js +25 -0
- package/dist/data-structures/linked-list/doubly-linked-list.js +259 -0
- package/dist/data-structures/linked-list/index.js +18 -0
- package/dist/data-structures/linked-list/singly-linked-list.js +660 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +2 -0
- package/dist/data-structures/matrix/index.js +19 -0
- package/dist/data-structures/matrix/matrix.js +14 -0
- package/dist/data-structures/matrix/matrix2d.js +119 -0
- package/dist/data-structures/matrix/navigator.js +78 -0
- package/dist/data-structures/matrix/vector2d.js +161 -0
- package/dist/data-structures/priority-queue/index.js +19 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/priority-queue.js +174 -0
- package/dist/data-structures/queue/deque.js +132 -0
- package/dist/data-structures/queue/index.js +17 -0
- package/dist/data-structures/queue/queue.js +113 -0
- package/dist/data-structures/stack/index.js +17 -0
- package/dist/data-structures/stack/stack.js +97 -0
- package/dist/data-structures/trampoline.js +52 -0
- package/dist/data-structures/trie/index.js +17 -0
- package/dist/data-structures/trie/trie.js +141 -0
- package/dist/index.js +17 -0
- package/dist/types/data-structures/binary-tree/aa-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +21 -0
- package/dist/types/data-structures/binary-tree/b-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +8 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +140 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +32 -0
- package/dist/types/data-structures/binary-tree/index.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +33 -0
- package/dist/types/data-structures/binary-tree/splay-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +11 -0
- package/dist/types/data-structures/binary-tree/two-three-tree.d.ts +2 -0
- package/dist/types/data-structures/graph/abstract-graph.d.ts +126 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +51 -0
- package/dist/types/data-structures/graph/index.d.ts +3 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +24 -0
- package/dist/types/data-structures/hash/coordinate-map.d.ts +8 -0
- package/dist/types/data-structures/hash/coordinate-set.d.ts +7 -0
- package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
- package/dist/types/data-structures/hash/index.d.ts +1 -0
- package/dist/types/data-structures/hash/pair.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
- package/dist/types/data-structures/heap/heap.d.ts +72 -0
- package/dist/types/data-structures/heap/index.d.ts +3 -0
- package/dist/types/data-structures/heap/max-heap.d.ts +14 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +14 -0
- package/dist/types/data-structures/index.d.ts +9 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +59 -0
- package/dist/types/data-structures/linked-list/index.d.ts +2 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +358 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
- package/dist/types/data-structures/matrix/index.d.ts +3 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +9 -0
- package/dist/types/data-structures/matrix/matrix2d.d.ts +25 -0
- package/dist/types/data-structures/matrix/navigator.d.ts +31 -0
- package/dist/types/data-structures/matrix/vector2d.d.ts +74 -0
- package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +36 -0
- package/dist/types/data-structures/queue/deque.d.ts +37 -0
- package/dist/types/data-structures/queue/index.d.ts +1 -0
- package/dist/types/data-structures/queue/queue.d.ts +76 -0
- package/dist/types/data-structures/stack/index.d.ts +1 -0
- package/dist/types/data-structures/stack/stack.d.ts +69 -0
- package/dist/types/data-structures/trampoline.d.ts +25 -0
- package/dist/types/data-structures/trie/index.d.ts +1 -0
- package/dist/types/data-structures/trie/trie.d.ts +28 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +17 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/utils.d.ts +46 -0
- package/dist/types/utils.d.ts +122 -0
- package/dist/types/utils.js +53 -0
- package/dist/utils.js +569 -0
- package/package.json +75 -0
- package/src/data-structures/binary-tree/aa-tree.ts +3 -0
- package/src/data-structures/binary-tree/avl-tree.ts +232 -0
- package/src/data-structures/binary-tree/b-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +33 -0
- package/src/data-structures/binary-tree/binary-tree.ts +1088 -0
- package/src/data-structures/binary-tree/bst.ts +404 -0
- package/src/data-structures/binary-tree/index.ts +4 -0
- package/src/data-structures/binary-tree/rb-tree.ts +3 -0
- package/src/data-structures/binary-tree/segment-tree.ts +164 -0
- package/src/data-structures/binary-tree/splay-tree.ts +3 -0
- package/src/data-structures/binary-tree/tree-multiset.ts +21 -0
- package/src/data-structures/binary-tree/two-three-tree.ts +3 -0
- package/src/data-structures/graph/abstract-graph.ts +789 -0
- package/src/data-structures/graph/directed-graph.ts +322 -0
- package/src/data-structures/graph/index.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +154 -0
- package/src/data-structures/hash/coordinate-map.ts +24 -0
- package/src/data-structures/hash/coordinate-set.ts +20 -0
- package/src/data-structures/hash/hash-table.ts +1 -0
- package/src/data-structures/hash/index.ts +1 -0
- package/src/data-structures/hash/pair.ts +1 -0
- package/src/data-structures/hash/tree-map.ts +1 -0
- package/src/data-structures/hash/tree-set.ts +1 -0
- package/src/data-structures/heap/heap.ts +136 -0
- package/src/data-structures/heap/index.ts +3 -0
- package/src/data-structures/heap/max-heap.ts +22 -0
- package/src/data-structures/heap/min-heap.ts +24 -0
- package/src/data-structures/index.ts +10 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +258 -0
- package/src/data-structures/linked-list/index.ts +2 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +750 -0
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -0
- package/src/data-structures/matrix/index.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +13 -0
- package/src/data-structures/matrix/matrix2d.ts +125 -0
- package/src/data-structures/matrix/navigator.ts +99 -0
- package/src/data-structures/matrix/vector2d.ts +189 -0
- package/src/data-structures/priority-queue/index.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/priority-queue.ts +208 -0
- package/src/data-structures/queue/deque.ts +139 -0
- package/src/data-structures/queue/index.ts +1 -0
- package/src/data-structures/queue/queue.ts +123 -0
- package/src/data-structures/stack/index.ts +1 -0
- package/src/data-structures/stack/stack.ts +104 -0
- package/src/data-structures/trampoline.ts +91 -0
- package/src/data-structures/trie/index.ts +1 -0
- package/src/data-structures/trie/trie.ts +153 -0
- package/src/index.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/types/patches/index.d.ts +0 -0
- package/src/types/utils.ts +158 -0
- package/src/utils.ts +605 -0
- package/tsconfig.json +52 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BinaryTree,
|
|
3
|
+
BinaryTreeNode,
|
|
4
|
+
BinaryTreeNodeId,
|
|
5
|
+
BinaryTreeNodePropertyName,
|
|
6
|
+
FamilyPosition,
|
|
7
|
+
LoopType,
|
|
8
|
+
} from './binary-tree';
|
|
9
|
+
|
|
10
|
+
export type BSTComparator = (a: BinaryTreeNodeId, b: BinaryTreeNodeId) => number;
|
|
11
|
+
export type BSTDeletedResult<T> = { deleted: BSTNode<T> | null, needBalanced: BSTNode<T> | null };
|
|
12
|
+
|
|
13
|
+
export enum CP {lt = -1, eq = 0, gt = 1}
|
|
14
|
+
|
|
15
|
+
export class BSTNode<T> extends BinaryTreeNode<T> {
|
|
16
|
+
override clone(): BSTNode<T> {
|
|
17
|
+
return new BSTNode<T>(this.id, this.val, this.count);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class BST<T> extends BinaryTree<T> {
|
|
22
|
+
protected _comparator: BSTComparator = (a, b) => a - b;
|
|
23
|
+
|
|
24
|
+
protected _compare(a: BinaryTreeNodeId, b: BinaryTreeNodeId): CP {
|
|
25
|
+
const compared = this._comparator(a, b);
|
|
26
|
+
if (compared > 0) return CP.gt;
|
|
27
|
+
else if (compared < 0) return CP.lt;
|
|
28
|
+
else return CP.eq;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
constructor(options?: {
|
|
32
|
+
comparator?: BSTComparator,
|
|
33
|
+
loopType?: LoopType
|
|
34
|
+
}) {
|
|
35
|
+
super(options);
|
|
36
|
+
if (options !== undefined) {
|
|
37
|
+
const {comparator} = options;
|
|
38
|
+
if (comparator !== undefined) {
|
|
39
|
+
this._comparator = comparator;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override createNode(id: BinaryTreeNodeId, val: T | null, count?: number): BSTNode<T> | null {
|
|
45
|
+
return val !== null ? new BSTNode<T>(id, val, count) : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override put(id: BinaryTreeNodeId, val: T | null, count: number = 1): BSTNode<T> | null {
|
|
49
|
+
let inserted: BSTNode<T> | null = null;
|
|
50
|
+
const newNode = this.createNode(id, val, count);
|
|
51
|
+
if (this.root === null) {
|
|
52
|
+
this.root = newNode;
|
|
53
|
+
this.size++;
|
|
54
|
+
this.count += newNode?.count ?? 1;
|
|
55
|
+
inserted = (this.root);
|
|
56
|
+
} else {
|
|
57
|
+
let cur = this.root;
|
|
58
|
+
let traversing = true;
|
|
59
|
+
while (traversing) {
|
|
60
|
+
if (cur !== null && newNode !== null) {
|
|
61
|
+
if (this._compare(cur.id, id) === CP.eq) {
|
|
62
|
+
if (newNode) {
|
|
63
|
+
cur.count += newNode.count;
|
|
64
|
+
this.count += newNode.count;
|
|
65
|
+
cur.val = newNode.val;
|
|
66
|
+
}
|
|
67
|
+
//Duplicates are not accepted.
|
|
68
|
+
traversing = false;
|
|
69
|
+
inserted = cur;
|
|
70
|
+
} else if (this._compare(cur.id, id) === CP.gt) {
|
|
71
|
+
// Traverse left of the node
|
|
72
|
+
if (cur.left === undefined) {
|
|
73
|
+
if (newNode) {
|
|
74
|
+
newNode.parent = cur;
|
|
75
|
+
newNode.familyPosition = FamilyPosition.left;
|
|
76
|
+
}
|
|
77
|
+
//Add to the left of the current node
|
|
78
|
+
cur.left = newNode;
|
|
79
|
+
this.size++;
|
|
80
|
+
this.count += newNode.count;
|
|
81
|
+
traversing = false;
|
|
82
|
+
inserted = cur.left;
|
|
83
|
+
} else {
|
|
84
|
+
//Traverse the left of the current node
|
|
85
|
+
if (cur.left) cur = cur.left;
|
|
86
|
+
}
|
|
87
|
+
} else if (this._compare(cur.id, id) === CP.lt) {
|
|
88
|
+
// Traverse right of the node
|
|
89
|
+
if (cur.right === undefined) {
|
|
90
|
+
if (newNode) {
|
|
91
|
+
newNode.parent = cur;
|
|
92
|
+
newNode.familyPosition = FamilyPosition.right;
|
|
93
|
+
}
|
|
94
|
+
//Add to the right of the current node
|
|
95
|
+
cur.right = newNode;
|
|
96
|
+
this.size++;
|
|
97
|
+
this.count += newNode.count;
|
|
98
|
+
traversing = false;
|
|
99
|
+
inserted = (cur.right);
|
|
100
|
+
} else {
|
|
101
|
+
//Traverse the left of the current node
|
|
102
|
+
if (cur.right) cur = cur.right;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
traversing = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return inserted;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
override get(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName): BSTNode<T> | null {
|
|
114
|
+
propertyName = propertyName ?? 'id';
|
|
115
|
+
return this.getNodes(nodeProperty, propertyName, true)[0] ?? null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
lastKey() {
|
|
119
|
+
if (this._compare(0, 1) === CP.lt) return this.getRightMost()?.id ?? 0;
|
|
120
|
+
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost()?.id ?? 0;
|
|
121
|
+
else return this.getRightMost()?.id ?? 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
override remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BSTDeletedResult<T>[] {
|
|
125
|
+
const bstDeletedResult: BSTDeletedResult<T>[] = [];
|
|
126
|
+
|
|
127
|
+
if (!this.root) return bstDeletedResult;
|
|
128
|
+
|
|
129
|
+
const curr: BSTNode<T> | null = this.get(id);
|
|
130
|
+
if (!curr) return bstDeletedResult;
|
|
131
|
+
|
|
132
|
+
const parent: BSTNode<T> | null = curr?.parent ? curr.parent : null;
|
|
133
|
+
let needBalanced: BSTNode<T> | null = null, orgCurrent = curr;
|
|
134
|
+
|
|
135
|
+
if (curr.count > 1 && !ignoreCount) {
|
|
136
|
+
curr.count--;
|
|
137
|
+
this.count--;
|
|
138
|
+
} else {
|
|
139
|
+
if (!curr.left) {
|
|
140
|
+
if (!parent) {
|
|
141
|
+
if (curr.right !== undefined) this.root = curr.right;
|
|
142
|
+
} else {
|
|
143
|
+
switch (curr.familyPosition) {
|
|
144
|
+
case FamilyPosition.left:
|
|
145
|
+
parent.left = curr.right;
|
|
146
|
+
break;
|
|
147
|
+
case FamilyPosition.right:
|
|
148
|
+
parent.right = curr.right;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
needBalanced = parent;
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
const leftSubTreeMax = curr.left ? this.getRightMost(curr.left) : null;
|
|
155
|
+
if (leftSubTreeMax) {
|
|
156
|
+
const parentOfLeftSubTreeMax = leftSubTreeMax.parent;
|
|
157
|
+
orgCurrent = curr.swapLocation(leftSubTreeMax);
|
|
158
|
+
if (parentOfLeftSubTreeMax) {
|
|
159
|
+
if (parentOfLeftSubTreeMax.right === leftSubTreeMax) parentOfLeftSubTreeMax.right = leftSubTreeMax.left;
|
|
160
|
+
else parentOfLeftSubTreeMax.left = leftSubTreeMax.left;
|
|
161
|
+
needBalanced = parentOfLeftSubTreeMax;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
this.size--;
|
|
166
|
+
this.count -= curr.count;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
bstDeletedResult.push({deleted: orgCurrent, needBalanced});
|
|
170
|
+
return bstDeletedResult;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
override getNodes(nodeProperty: BinaryTreeNodeId | T, propertyName ?: BinaryTreeNodePropertyName, onlyOne ?: boolean): BSTNode<T>[] {
|
|
174
|
+
propertyName = propertyName ?? 'id';
|
|
175
|
+
if (!this.root) return [];
|
|
176
|
+
const result: BSTNode<T>[] = [];
|
|
177
|
+
|
|
178
|
+
if (this._loopType === LoopType.recursive) {
|
|
179
|
+
const _traverse = (cur: BSTNode<T>) => {
|
|
180
|
+
if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return;
|
|
181
|
+
|
|
182
|
+
if (!cur.left && !cur.right) return;
|
|
183
|
+
if (propertyName === 'id') {
|
|
184
|
+
if (this._compare(cur.id, nodeProperty as number) === CP.gt) cur.left && _traverse(cur.left);
|
|
185
|
+
if (this._compare(cur.id, nodeProperty as number) === CP.lt) cur.right && _traverse(cur.right);
|
|
186
|
+
} else {
|
|
187
|
+
cur.left && _traverse(cur.left);
|
|
188
|
+
cur.right && _traverse(cur.right);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
_traverse(this.root);
|
|
193
|
+
} else {
|
|
194
|
+
const queue: BSTNode<T>[] = [this.root];
|
|
195
|
+
while (queue.length > 0) {
|
|
196
|
+
const cur = queue.shift();
|
|
197
|
+
if (cur) {
|
|
198
|
+
if (this._pushByPropertyNameStopOrNot(cur, result, nodeProperty, propertyName, onlyOne)) return result;
|
|
199
|
+
if (propertyName === 'id') {
|
|
200
|
+
if (this._compare(cur.id, nodeProperty as number) === CP.gt) cur.left && queue.push(cur.left);
|
|
201
|
+
if (this._compare(cur.id, nodeProperty as number) === CP.lt) cur.right && queue.push(cur.right);
|
|
202
|
+
} else {
|
|
203
|
+
cur.left && queue.push(cur.left);
|
|
204
|
+
cur.right && queue.push(cur.right);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// --- start additional functions
|
|
214
|
+
lesserSum(id: BinaryTreeNodeId, propertyName ?: BinaryTreeNodePropertyName): number {
|
|
215
|
+
propertyName = propertyName ?? 'id';
|
|
216
|
+
if (!this.root) return 0;
|
|
217
|
+
|
|
218
|
+
const getSumByPropertyName = (cur: BSTNode<T>) => {
|
|
219
|
+
let needSum: number;
|
|
220
|
+
switch (propertyName) {
|
|
221
|
+
case 'id':
|
|
222
|
+
needSum = cur.id;
|
|
223
|
+
break;
|
|
224
|
+
case 'count':
|
|
225
|
+
needSum = cur.count;
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
needSum = cur.id;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
return needSum;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let sum = 0;
|
|
235
|
+
|
|
236
|
+
if (this._loopType === LoopType.recursive) {
|
|
237
|
+
const _traverse = (cur: BSTNode<T>): void => {
|
|
238
|
+
const compared = this._compare(cur.id, id);
|
|
239
|
+
if (compared === CP.eq) {
|
|
240
|
+
if (cur.right) sum += this.subTreeSum(cur.right, propertyName);
|
|
241
|
+
return;
|
|
242
|
+
} else if (compared === CP.lt) {
|
|
243
|
+
if (cur.left) sum += this.subTreeSum(cur.left, propertyName);
|
|
244
|
+
sum += getSumByPropertyName(cur);
|
|
245
|
+
if (cur.right) _traverse(cur.right);
|
|
246
|
+
else return;
|
|
247
|
+
} else {
|
|
248
|
+
if (cur.left) _traverse(cur.left);
|
|
249
|
+
else return;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
_traverse(this.root);
|
|
254
|
+
} else {
|
|
255
|
+
const queue: BSTNode<T>[] = [this.root];
|
|
256
|
+
while (queue.length > 0) {
|
|
257
|
+
const cur = queue.shift();
|
|
258
|
+
if (cur) {
|
|
259
|
+
const compared = this._compare(cur.id, id);
|
|
260
|
+
if (compared === CP.eq) {
|
|
261
|
+
if (cur.right) sum += this.subTreeSum(cur.right, propertyName);
|
|
262
|
+
return sum;
|
|
263
|
+
} else if (compared === CP.lt) { // todo maybe a bug
|
|
264
|
+
if (cur.left) sum += this.subTreeSum(cur.left, propertyName);
|
|
265
|
+
sum += getSumByPropertyName(cur);
|
|
266
|
+
if (cur.right) queue.push(cur.right);
|
|
267
|
+
else return sum;
|
|
268
|
+
} else {
|
|
269
|
+
if (cur.left) queue.push(cur.left);
|
|
270
|
+
else return sum;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return sum;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
allGreaterNodesAdd(node: BSTNode<T>, delta: number, propertyName ?: BinaryTreeNodePropertyName): boolean {
|
|
280
|
+
propertyName = propertyName ?? 'id';
|
|
281
|
+
if (!this.root) return false;
|
|
282
|
+
|
|
283
|
+
const _sumByPropertyName = (cur: BSTNode<T>) => {
|
|
284
|
+
switch (propertyName) {
|
|
285
|
+
case 'id':
|
|
286
|
+
cur.id += delta;
|
|
287
|
+
break;
|
|
288
|
+
case 'count':
|
|
289
|
+
cur.count += delta;
|
|
290
|
+
break;
|
|
291
|
+
default:
|
|
292
|
+
cur.id += delta;
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (this._loopType === LoopType.recursive) {
|
|
298
|
+
const _traverse = (cur: BSTNode<T>) => {
|
|
299
|
+
const compared = this._compare(cur.id, node.id);
|
|
300
|
+
_sumByPropertyName(cur);
|
|
301
|
+
|
|
302
|
+
if (!cur.left && !cur.right) return;
|
|
303
|
+
if (cur.left && compared === CP.gt) _traverse(cur.left);
|
|
304
|
+
else if (cur.right && compared === CP.gt) _traverse(cur.right);
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
_traverse(this.root);
|
|
308
|
+
return true;
|
|
309
|
+
} else {
|
|
310
|
+
const queue: BSTNode<T>[] = [this.root];
|
|
311
|
+
while (queue.length > 0) {
|
|
312
|
+
const cur = queue.shift();
|
|
313
|
+
if (cur) {
|
|
314
|
+
const compared = this._compare(cur.id, node.id);
|
|
315
|
+
_sumByPropertyName(cur);
|
|
316
|
+
|
|
317
|
+
if (cur.left && compared === CP.gt) queue.push(cur.left);
|
|
318
|
+
else if (cur.right && compared === CP.gt) queue.push(cur.right);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
balance(): boolean {
|
|
326
|
+
const sorted = this.DFS('in', 'node'), n = sorted.length;
|
|
327
|
+
this.clear();
|
|
328
|
+
|
|
329
|
+
if (sorted.length < 1) return false;
|
|
330
|
+
if (this._loopType === LoopType.recursive) {
|
|
331
|
+
const buildBalanceBST = (l: number, r: number) => {
|
|
332
|
+
if (l > r) return;
|
|
333
|
+
const m = l + Math.floor((r - l) / 2);
|
|
334
|
+
const midNode = sorted[m];
|
|
335
|
+
this.put(midNode.id, midNode.val, midNode.count);
|
|
336
|
+
buildBalanceBST(l, m - 1);
|
|
337
|
+
buildBalanceBST(m + 1, r);
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
buildBalanceBST(0, n - 1);
|
|
341
|
+
return true;
|
|
342
|
+
} else {
|
|
343
|
+
const stack: [[number, number]] = [[0, n - 1]];
|
|
344
|
+
while (stack.length > 0) {
|
|
345
|
+
const popped = stack.pop();
|
|
346
|
+
if (popped) {
|
|
347
|
+
const [l, r] = popped;
|
|
348
|
+
if (l <= r) {
|
|
349
|
+
const m = l + Math.floor((r - l) / 2);
|
|
350
|
+
const midNode = sorted[m];
|
|
351
|
+
this.put(midNode.id, midNode.val, midNode.count);
|
|
352
|
+
stack.push([m + 1, r]);
|
|
353
|
+
stack.push([l, m - 1]);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
isAVLBalanced(): boolean {
|
|
362
|
+
if (!this.root) return true;
|
|
363
|
+
|
|
364
|
+
let balanced = true;
|
|
365
|
+
|
|
366
|
+
if (this._loopType === LoopType.recursive) {
|
|
367
|
+
const _height = (cur: BSTNode<T> | null | undefined): number => {
|
|
368
|
+
if (!cur) return 0;
|
|
369
|
+
const leftHeight = _height(cur.left), rightHeight = _height(cur.right);
|
|
370
|
+
if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;
|
|
371
|
+
return Math.max(leftHeight, rightHeight) + 1;
|
|
372
|
+
};
|
|
373
|
+
_height(this.root);
|
|
374
|
+
} else {
|
|
375
|
+
const stack: BSTNode<T>[] = [];
|
|
376
|
+
let node: BSTNode<T> | null | undefined = this.root, last: BSTNode<T> | null = null,
|
|
377
|
+
depths: Map<BSTNode<T>, number> = new Map();
|
|
378
|
+
|
|
379
|
+
while (stack.length > 0 || node) {
|
|
380
|
+
if (node) {
|
|
381
|
+
stack.push(node);
|
|
382
|
+
node = node.left;
|
|
383
|
+
} else {
|
|
384
|
+
node = stack[stack.length - 1]
|
|
385
|
+
if (!node.right || last === node.right) {
|
|
386
|
+
node = stack.pop();
|
|
387
|
+
if (node) {
|
|
388
|
+
let left = node.left ? depths.get(node.left) ?? -1 : -1;
|
|
389
|
+
let right = node.right ? depths.get(node.right) ?? -1 : -1;
|
|
390
|
+
if (Math.abs(left - right) > 1) return false;
|
|
391
|
+
depths.set(node, 1 + Math.max(left, right));
|
|
392
|
+
last = node;
|
|
393
|
+
node = null;
|
|
394
|
+
}
|
|
395
|
+
} else node = node.right
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return balanced;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// --- end additional functions
|
|
404
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export type SegmentTreeNodeVal = number;
|
|
2
|
+
|
|
3
|
+
export class SegmentTreeNode {
|
|
4
|
+
protected _start = 0;
|
|
5
|
+
get start(): number {
|
|
6
|
+
return this._start;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
set start(v: number) {
|
|
10
|
+
this._start = v;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
protected _end = 0;
|
|
14
|
+
get end(): number {
|
|
15
|
+
return this._end;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
set end(v: number) {
|
|
19
|
+
this._end = v;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected _val: SegmentTreeNodeVal | null = null;
|
|
23
|
+
get val(): SegmentTreeNodeVal | null {
|
|
24
|
+
return this._val;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
set val(v: SegmentTreeNodeVal | null) {
|
|
28
|
+
this._val = v;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
protected _sum = 0;
|
|
32
|
+
get sum(): number {
|
|
33
|
+
return this._sum;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set sum(v: number) {
|
|
37
|
+
this._sum = v;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
protected _left: SegmentTreeNode | null = null;
|
|
41
|
+
get left(): SegmentTreeNode | null {
|
|
42
|
+
return this._left;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
set left(v: SegmentTreeNode | null) {
|
|
46
|
+
this._left = v;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected _right: SegmentTreeNode | null = null;
|
|
50
|
+
get right(): SegmentTreeNode | null {
|
|
51
|
+
return this._right;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
set right(v: SegmentTreeNode | null) {
|
|
55
|
+
this._right = v;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
constructor(start: number, end: number, sum: number, val?: SegmentTreeNodeVal | null) {
|
|
59
|
+
this._start = start;
|
|
60
|
+
this._end = end;
|
|
61
|
+
this._sum = sum;
|
|
62
|
+
this._val = val || null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class SegmentTree {
|
|
67
|
+
protected _values: number[] = [];
|
|
68
|
+
protected _start = 0;
|
|
69
|
+
protected _end: number;
|
|
70
|
+
protected _root: SegmentTreeNode | null;
|
|
71
|
+
get root(): SegmentTreeNode | null {
|
|
72
|
+
return this._root;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
constructor(values: number[], start?: number, end?: number) {
|
|
76
|
+
start = start || 0;
|
|
77
|
+
end = end || values.length - 1;
|
|
78
|
+
this._values = values;
|
|
79
|
+
this._start = start;
|
|
80
|
+
this._end = end;
|
|
81
|
+
this._root = this.build(start, end);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
build(start: number, end: number): SegmentTreeNode {
|
|
85
|
+
if (start === end) {
|
|
86
|
+
return new SegmentTreeNode(start, end, this._values[start]);
|
|
87
|
+
}
|
|
88
|
+
const mid = start + Math.floor((end - start) / 2);
|
|
89
|
+
const left = this.build(start, mid);
|
|
90
|
+
const right = this.build(mid + 1, end);
|
|
91
|
+
const cur = new SegmentTreeNode(start, end, left.sum + right.sum);
|
|
92
|
+
cur.left = left;
|
|
93
|
+
cur.right = right;
|
|
94
|
+
return cur;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
updateNode(index: number, sum: number, val?: SegmentTreeNodeVal) {
|
|
98
|
+
const root = this.root || null;
|
|
99
|
+
if (!root) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const dfs = (cur: SegmentTreeNode, index: number, sum: number, val?: SegmentTreeNodeVal) => {
|
|
103
|
+
if (cur.start === cur.end && cur.start === index) {
|
|
104
|
+
cur.sum = sum;
|
|
105
|
+
// cur.val = val;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const mid = cur.start + Math.floor((cur.end - cur.start) / 2);
|
|
109
|
+
if (index <= mid) {
|
|
110
|
+
if (cur.left) {
|
|
111
|
+
dfs(cur.left, index, sum, val);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
if (cur.right) {
|
|
115
|
+
dfs(cur.right, index, sum, val);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (cur.left && cur.right) {
|
|
119
|
+
cur.sum = cur.left.sum + cur.right.sum;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
dfs(root, index, sum);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
querySumByRange(indexA: number, indexB: number): number {
|
|
127
|
+
const root = this.root || null;
|
|
128
|
+
if (!root) {
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const dfs = (cur: SegmentTreeNode, i: number, j: number): number => {
|
|
133
|
+
if (cur.start === i && cur.end === j) {
|
|
134
|
+
return cur.sum;
|
|
135
|
+
}
|
|
136
|
+
const mid = cur.start + Math.floor((cur.end - cur.start) / 2);
|
|
137
|
+
if (j <= mid) {
|
|
138
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
139
|
+
if (cur.left) {
|
|
140
|
+
return dfs(cur.left, i, j);
|
|
141
|
+
} else {
|
|
142
|
+
return NaN;
|
|
143
|
+
}
|
|
144
|
+
} else if (i > mid) {
|
|
145
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
146
|
+
if (cur.right) {
|
|
147
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
148
|
+
return dfs(cur.right, i, j);
|
|
149
|
+
|
|
150
|
+
} else {
|
|
151
|
+
return NaN;
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
// TODO after no-non-null-assertion not ensure the logic
|
|
155
|
+
if (cur.left && cur.right) {
|
|
156
|
+
return dfs(cur.left, i, mid) + dfs(cur.right, mid + 1, j);
|
|
157
|
+
} else {
|
|
158
|
+
return NaN;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return dfs(root, indexA, indexB);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {BST, BSTNode} from './bst';
|
|
2
|
+
import {BinaryTreeNodeId} from './binary-tree';
|
|
3
|
+
|
|
4
|
+
export type TreeMultiSetDeletedResult<T> = { deleted: BSTNode<T> | null, needBalanced: BSTNode<T> | null };
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export class TreeMultiSet<T> extends BST<T> {
|
|
8
|
+
override createNode(id: BinaryTreeNodeId, val: T, count?: number): BSTNode<T> {
|
|
9
|
+
return new BSTNode<T>(id, val, count);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
override put(id: BinaryTreeNodeId, val: T | null, count?: number): BSTNode<T> | null {
|
|
13
|
+
return super.put(id, val, count);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override remove(id: BinaryTreeNodeId, isUpdateAllLeftSum?: boolean): TreeMultiSetDeletedResult<T>[] {
|
|
17
|
+
return super.remove(id, isUpdateAllLeftSum);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|