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.
Files changed (166) hide show
  1. package/.idea/data-structure-typed.iml +12 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/README.md +2 -0
  5. package/dist/data-structures/binary-tree/aa-tree.js +6 -0
  6. package/dist/data-structures/binary-tree/avl-tree.js +231 -0
  7. package/dist/data-structures/binary-tree/b-tree.js +6 -0
  8. package/dist/data-structures/binary-tree/binary-indexed-tree.js +31 -0
  9. package/dist/data-structures/binary-tree/binary-tree.js +992 -0
  10. package/dist/data-structures/binary-tree/bst.js +431 -0
  11. package/dist/data-structures/binary-tree/index.js +20 -0
  12. package/dist/data-structures/binary-tree/rb-tree.js +6 -0
  13. package/dist/data-structures/binary-tree/segment-tree.js +151 -0
  14. package/dist/data-structures/binary-tree/splay-tree.js +6 -0
  15. package/dist/data-structures/binary-tree/tree-multiset.js +16 -0
  16. package/dist/data-structures/binary-tree/two-three-tree.js +6 -0
  17. package/dist/data-structures/graph/abstract-graph.js +648 -0
  18. package/dist/data-structures/graph/directed-graph.js +268 -0
  19. package/dist/data-structures/graph/index.js +19 -0
  20. package/dist/data-structures/graph/undirected-graph.js +142 -0
  21. package/dist/data-structures/hash/coordinate-map.js +24 -0
  22. package/dist/data-structures/hash/coordinate-set.js +21 -0
  23. package/dist/data-structures/hash/hash-table.js +2 -0
  24. package/dist/data-structures/hash/index.js +17 -0
  25. package/dist/data-structures/hash/pair.js +2 -0
  26. package/dist/data-structures/hash/tree-map.js +2 -0
  27. package/dist/data-structures/hash/tree-set.js +2 -0
  28. package/dist/data-structures/heap/heap.js +114 -0
  29. package/dist/data-structures/heap/index.js +19 -0
  30. package/dist/data-structures/heap/max-heap.js +22 -0
  31. package/dist/data-structures/heap/min-heap.js +22 -0
  32. package/dist/data-structures/index.js +25 -0
  33. package/dist/data-structures/linked-list/doubly-linked-list.js +259 -0
  34. package/dist/data-structures/linked-list/index.js +18 -0
  35. package/dist/data-structures/linked-list/singly-linked-list.js +660 -0
  36. package/dist/data-structures/linked-list/skip-linked-list.js +2 -0
  37. package/dist/data-structures/matrix/index.js +19 -0
  38. package/dist/data-structures/matrix/matrix.js +14 -0
  39. package/dist/data-structures/matrix/matrix2d.js +119 -0
  40. package/dist/data-structures/matrix/navigator.js +78 -0
  41. package/dist/data-structures/matrix/vector2d.js +161 -0
  42. package/dist/data-structures/priority-queue/index.js +19 -0
  43. package/dist/data-structures/priority-queue/max-priority-queue.js +15 -0
  44. package/dist/data-structures/priority-queue/min-priority-queue.js +15 -0
  45. package/dist/data-structures/priority-queue/priority-queue.js +174 -0
  46. package/dist/data-structures/queue/deque.js +132 -0
  47. package/dist/data-structures/queue/index.js +17 -0
  48. package/dist/data-structures/queue/queue.js +113 -0
  49. package/dist/data-structures/stack/index.js +17 -0
  50. package/dist/data-structures/stack/stack.js +97 -0
  51. package/dist/data-structures/trampoline.js +52 -0
  52. package/dist/data-structures/trie/index.js +17 -0
  53. package/dist/data-structures/trie/trie.js +141 -0
  54. package/dist/index.js +17 -0
  55. package/dist/types/data-structures/binary-tree/aa-tree.d.ts +2 -0
  56. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +21 -0
  57. package/dist/types/data-structures/binary-tree/b-tree.d.ts +2 -0
  58. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +8 -0
  59. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +140 -0
  60. package/dist/types/data-structures/binary-tree/bst.d.ts +32 -0
  61. package/dist/types/data-structures/binary-tree/index.d.ts +4 -0
  62. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -0
  63. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +33 -0
  64. package/dist/types/data-structures/binary-tree/splay-tree.d.ts +2 -0
  65. package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +11 -0
  66. package/dist/types/data-structures/binary-tree/two-three-tree.d.ts +2 -0
  67. package/dist/types/data-structures/graph/abstract-graph.d.ts +126 -0
  68. package/dist/types/data-structures/graph/directed-graph.d.ts +51 -0
  69. package/dist/types/data-structures/graph/index.d.ts +3 -0
  70. package/dist/types/data-structures/graph/undirected-graph.d.ts +24 -0
  71. package/dist/types/data-structures/hash/coordinate-map.d.ts +8 -0
  72. package/dist/types/data-structures/hash/coordinate-set.d.ts +7 -0
  73. package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
  74. package/dist/types/data-structures/hash/index.d.ts +1 -0
  75. package/dist/types/data-structures/hash/pair.d.ts +1 -0
  76. package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
  77. package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
  78. package/dist/types/data-structures/heap/heap.d.ts +72 -0
  79. package/dist/types/data-structures/heap/index.d.ts +3 -0
  80. package/dist/types/data-structures/heap/max-heap.d.ts +14 -0
  81. package/dist/types/data-structures/heap/min-heap.d.ts +14 -0
  82. package/dist/types/data-structures/index.d.ts +9 -0
  83. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +59 -0
  84. package/dist/types/data-structures/linked-list/index.d.ts +2 -0
  85. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +358 -0
  86. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
  87. package/dist/types/data-structures/matrix/index.d.ts +3 -0
  88. package/dist/types/data-structures/matrix/matrix.d.ts +9 -0
  89. package/dist/types/data-structures/matrix/matrix2d.d.ts +25 -0
  90. package/dist/types/data-structures/matrix/navigator.d.ts +31 -0
  91. package/dist/types/data-structures/matrix/vector2d.d.ts +74 -0
  92. package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
  93. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +4 -0
  94. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +4 -0
  95. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +36 -0
  96. package/dist/types/data-structures/queue/deque.d.ts +37 -0
  97. package/dist/types/data-structures/queue/index.d.ts +1 -0
  98. package/dist/types/data-structures/queue/queue.d.ts +76 -0
  99. package/dist/types/data-structures/stack/index.d.ts +1 -0
  100. package/dist/types/data-structures/stack/stack.d.ts +69 -0
  101. package/dist/types/data-structures/trampoline.d.ts +25 -0
  102. package/dist/types/data-structures/trie/index.d.ts +1 -0
  103. package/dist/types/data-structures/trie/trie.d.ts +28 -0
  104. package/dist/types/index.d.ts +1 -0
  105. package/dist/types/index.js +17 -0
  106. package/dist/types/types/index.d.ts +1 -0
  107. package/dist/types/types/utils.d.ts +46 -0
  108. package/dist/types/utils.d.ts +122 -0
  109. package/dist/types/utils.js +53 -0
  110. package/dist/utils.js +569 -0
  111. package/package.json +75 -0
  112. package/src/data-structures/binary-tree/aa-tree.ts +3 -0
  113. package/src/data-structures/binary-tree/avl-tree.ts +232 -0
  114. package/src/data-structures/binary-tree/b-tree.ts +3 -0
  115. package/src/data-structures/binary-tree/binary-indexed-tree.ts +33 -0
  116. package/src/data-structures/binary-tree/binary-tree.ts +1088 -0
  117. package/src/data-structures/binary-tree/bst.ts +404 -0
  118. package/src/data-structures/binary-tree/index.ts +4 -0
  119. package/src/data-structures/binary-tree/rb-tree.ts +3 -0
  120. package/src/data-structures/binary-tree/segment-tree.ts +164 -0
  121. package/src/data-structures/binary-tree/splay-tree.ts +3 -0
  122. package/src/data-structures/binary-tree/tree-multiset.ts +21 -0
  123. package/src/data-structures/binary-tree/two-three-tree.ts +3 -0
  124. package/src/data-structures/graph/abstract-graph.ts +789 -0
  125. package/src/data-structures/graph/directed-graph.ts +322 -0
  126. package/src/data-structures/graph/index.ts +3 -0
  127. package/src/data-structures/graph/undirected-graph.ts +154 -0
  128. package/src/data-structures/hash/coordinate-map.ts +24 -0
  129. package/src/data-structures/hash/coordinate-set.ts +20 -0
  130. package/src/data-structures/hash/hash-table.ts +1 -0
  131. package/src/data-structures/hash/index.ts +1 -0
  132. package/src/data-structures/hash/pair.ts +1 -0
  133. package/src/data-structures/hash/tree-map.ts +1 -0
  134. package/src/data-structures/hash/tree-set.ts +1 -0
  135. package/src/data-structures/heap/heap.ts +136 -0
  136. package/src/data-structures/heap/index.ts +3 -0
  137. package/src/data-structures/heap/max-heap.ts +22 -0
  138. package/src/data-structures/heap/min-heap.ts +24 -0
  139. package/src/data-structures/index.ts +10 -0
  140. package/src/data-structures/linked-list/doubly-linked-list.ts +258 -0
  141. package/src/data-structures/linked-list/index.ts +2 -0
  142. package/src/data-structures/linked-list/singly-linked-list.ts +750 -0
  143. package/src/data-structures/linked-list/skip-linked-list.ts +1 -0
  144. package/src/data-structures/matrix/index.ts +3 -0
  145. package/src/data-structures/matrix/matrix.ts +13 -0
  146. package/src/data-structures/matrix/matrix2d.ts +125 -0
  147. package/src/data-structures/matrix/navigator.ts +99 -0
  148. package/src/data-structures/matrix/vector2d.ts +189 -0
  149. package/src/data-structures/priority-queue/index.ts +3 -0
  150. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -0
  151. package/src/data-structures/priority-queue/min-priority-queue.ts +12 -0
  152. package/src/data-structures/priority-queue/priority-queue.ts +208 -0
  153. package/src/data-structures/queue/deque.ts +139 -0
  154. package/src/data-structures/queue/index.ts +1 -0
  155. package/src/data-structures/queue/queue.ts +123 -0
  156. package/src/data-structures/stack/index.ts +1 -0
  157. package/src/data-structures/stack/stack.ts +104 -0
  158. package/src/data-structures/trampoline.ts +91 -0
  159. package/src/data-structures/trie/index.ts +1 -0
  160. package/src/data-structures/trie/trie.ts +153 -0
  161. package/src/index.ts +1 -0
  162. package/src/types/index.ts +1 -0
  163. package/src/types/patches/index.d.ts +0 -0
  164. package/src/types/utils.ts +158 -0
  165. package/src/utils.ts +605 -0
  166. package/tsconfig.json +52 -0
@@ -0,0 +1,789 @@
1
+ import {arrayRemove, uuidV4} from '../../utils';
2
+ import {PriorityQueue} from '../priority-queue';
3
+
4
+ export type VertexId = string | number;
5
+ export type DijkstraResult<V> =
6
+ { distMap: Map<V, number>, preMap: Map<V, V | null>, seen: Set<V>, paths: V[][], minDist: number, minPath: V[] }
7
+ | null;
8
+
9
+ export interface I_Graph<V, E> {
10
+
11
+ containsVertex(vertexOrId: V | VertexId): boolean;
12
+
13
+ getVertex(vertexOrId: VertexId | V): V | null;
14
+
15
+ getVertexId(vertexOrId: V | VertexId): VertexId;
16
+
17
+ vertexSet(): Map<VertexId, V>;
18
+
19
+ addVertex(v: V): boolean;
20
+
21
+ removeVertex(vertexOrId: V | VertexId): boolean;
22
+
23
+ removeAllVertices(vertices: V[] | VertexId[]): boolean;
24
+
25
+ degreeOf(vertexOrId: V | VertexId): number;
26
+
27
+ edgesOf(vertexOrId: V | VertexId): E[];
28
+
29
+ containsEdge(src: V | VertexId, dest: V | VertexId): boolean;
30
+
31
+ // containsEdge(e: E): boolean;
32
+
33
+ getEdge(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
34
+
35
+ // getAllEdges(src: V, dest: V): E[];
36
+
37
+ edgeSet(): E[];
38
+
39
+ addEdge(edge: E): boolean;
40
+
41
+ removeEdgeBetween(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
42
+
43
+ removeEdge(edge: E): E | null;
44
+
45
+ // removeAllEdges(v1: VertexId | V, v2: VertexId | V): (E | null)[];
46
+
47
+ // removeAllEdges(edges: E[] | [VertexId, VertexId]): boolean;
48
+
49
+ setEdgeWeight(srcOrId: V | VertexId, destOrId: V | VertexId, weight: number): boolean;
50
+
51
+ getMinPathBetween(v1: V | VertexId, v2: V | VertexId, isWeight?: boolean): V[] | null;
52
+
53
+ getNeighbors(vertexOrId: V | VertexId): V[];
54
+ }
55
+
56
+ export class AbstractVertex {
57
+ private _id: VertexId;
58
+ public get id(): VertexId {
59
+ return this._id;
60
+ }
61
+
62
+ public set id(v: VertexId) {
63
+ this._id = v;
64
+ }
65
+
66
+ constructor(id: VertexId) {
67
+ this._id = id;
68
+ }
69
+ }
70
+
71
+ export abstract class AbstractEdge {
72
+
73
+ private _weight: number;
74
+ get weight(): number {
75
+ return this._weight;
76
+ }
77
+
78
+ set weight(v: number) {
79
+ this._weight = v;
80
+ }
81
+
82
+ private _hashCode: string;
83
+
84
+ get hashCode(): string {
85
+ return this._hashCode;
86
+ }
87
+
88
+ set hashCode(v: string) {
89
+ this._hashCode = v;
90
+ }
91
+
92
+ protected constructor(weight?: number) {
93
+ if (weight === undefined) weight = AbstractEdge.DEFAULT_EDGE_WEIGHT;
94
+ this._weight = weight;
95
+ this._hashCode = uuidV4();
96
+ }
97
+
98
+ static DEFAULT_EDGE_WEIGHT = 1;
99
+ }
100
+
101
+ // Connected Component === Largest Connected Sub-Graph
102
+ export abstract class AbstractGraph<V extends AbstractVertex, E extends AbstractEdge> implements I_Graph<V, E> {
103
+
104
+ protected _vertices: Map<VertexId, V> = new Map<VertexId, V>();
105
+
106
+ abstract removeEdgeBetween(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;
107
+
108
+ abstract removeEdge(edge: E): E | null;
109
+
110
+ getVertex(vertexOrId: VertexId | V): V | null {
111
+ const vertexId = this.getVertexId(vertexOrId);
112
+ return this._vertices.get(vertexId) || null;
113
+ }
114
+
115
+ getVertexId(vertexOrId: V | VertexId): VertexId {
116
+ return vertexOrId instanceof AbstractVertex ? vertexOrId.id : vertexOrId;
117
+ }
118
+
119
+ containsVertex(vertexOrId: V | VertexId): boolean {
120
+ return this._vertices.has(this.getVertexId(vertexOrId));
121
+ }
122
+
123
+ vertexSet(): Map<VertexId, V> {
124
+ return this._vertices;
125
+ }
126
+
127
+ abstract getEdge(srcOrId: V | null | VertexId, destOrId: V | null | VertexId): E | null;
128
+
129
+ addVertex(newVertex: V): boolean {
130
+ if (this.containsVertex(newVertex)) {
131
+ return false;
132
+ }
133
+ this._vertices.set(newVertex.id, newVertex);
134
+ return true;
135
+ }
136
+
137
+ removeVertex(vertexOrId: V | VertexId): boolean {
138
+ const vertexId = this.getVertexId(vertexOrId);
139
+ return this._vertices.delete(vertexId);
140
+ }
141
+
142
+ removeAllVertices(vertices: V[] | VertexId[]): boolean {
143
+ const removed: boolean[] = [];
144
+ for (const v of vertices) {
145
+ removed.push(this.removeVertex(v));
146
+ }
147
+ return removed.length > 0;
148
+ }
149
+
150
+ abstract degreeOf(vertexOrId: V | VertexId): number;
151
+
152
+ abstract edgeSet(): E[];
153
+
154
+ abstract edgesOf(vertexOrId: V | VertexId): E[];
155
+
156
+ containsEdge(v1: VertexId | V, v2: VertexId | V): boolean {
157
+ const edge = this.getEdge(v1, v2);
158
+ return !!edge;
159
+ }
160
+
161
+ abstract addEdge(edge: E): boolean;
162
+
163
+ setEdgeWeight(srcOrId: VertexId | V, destOrId: VertexId | V, weight: number): boolean {
164
+ const edge = this.getEdge(srcOrId, destOrId);
165
+ if (edge) {
166
+ edge.weight = weight;
167
+ return true;
168
+ } else {
169
+ return false;
170
+ }
171
+ }
172
+
173
+ abstract getNeighbors(vertexOrId: V | VertexId): V[];
174
+
175
+ getAllPathsBetween(v1: V | VertexId, v2: V | VertexId): V[][] {
176
+ const paths: V[][] = [];
177
+ const vertex1 = this.getVertex(v1);
178
+ const vertex2 = this.getVertex(v2);
179
+ if (!(vertex1 && vertex2)) {
180
+ return [];
181
+ }
182
+
183
+ const dfs = (cur: V, dest: V, visiting: Map<V, boolean>, path: V[]) => {
184
+ visiting.set(cur, true);
185
+
186
+ if (cur === dest) {
187
+ paths.push([vertex1, ...path]);
188
+ }
189
+
190
+ const neighbors = this.getNeighbors(cur);
191
+ for (const neighbor of neighbors) {
192
+ if (!visiting.get(neighbor)) {
193
+ path.push(neighbor);
194
+ dfs(neighbor, dest, visiting, path);
195
+ arrayRemove(path, vertex => vertex === neighbor);
196
+ }
197
+ }
198
+
199
+ visiting.set(cur, false);
200
+ };
201
+
202
+ dfs(vertex1, vertex2, new Map<V, boolean>(), []);
203
+ return paths;
204
+ }
205
+
206
+
207
+ getPathSumWeight(path: V[]): number {
208
+ let sum = 0;
209
+ for (let i = 0; i < path.length; i++) {
210
+ sum += this.getEdge(path[i], path[i + 1])?.weight || 0;
211
+ }
212
+ return sum;
213
+ }
214
+
215
+ getMinCostBetween(v1: V | VertexId, v2: V | VertexId, isWeight?: boolean): number | null {
216
+ if (isWeight === undefined) isWeight = false;
217
+
218
+ if (isWeight) {
219
+ const allPaths = this.getAllPathsBetween(v1, v2);
220
+ let min = Infinity;
221
+ for (const path of allPaths) {
222
+ min = Math.min(this.getPathSumWeight(path), min);
223
+ }
224
+ return min;
225
+ } else {
226
+ // BFS
227
+ const vertex2 = this.getVertex(v2);
228
+ const vertex1 = this.getVertex(v1);
229
+ if (!(vertex1 && vertex2)) {
230
+ return null;
231
+ }
232
+
233
+ const visited: Map<V, boolean> = new Map();
234
+ const queue: V[] = [vertex1];
235
+ visited.set(vertex1, true);
236
+ let cost = 0;
237
+ while (queue.length > 0) {
238
+ for (let i = 0; i < queue.length; i++) {
239
+ const cur = queue.shift();
240
+ if (cur === vertex2) {
241
+ return cost;
242
+ }
243
+ // TODO consider optimizing to AbstractGraph
244
+ if (cur !== undefined) {
245
+ const neighbors = this.getNeighbors(cur);
246
+ for (const neighbor of neighbors) {
247
+ if (!visited.has(neighbor)) {
248
+ visited.set(neighbor, true);
249
+ queue.push(neighbor);
250
+ }
251
+ }
252
+ }
253
+ }
254
+ cost++;
255
+ }
256
+ return null;
257
+ }
258
+ }
259
+
260
+ getMinPathBetween(v1: V | VertexId, v2: V | VertexId, isWeight?: boolean): V[] | null {
261
+ if (isWeight === undefined) isWeight = false;
262
+
263
+ if (isWeight) {
264
+ const allPaths = this.getAllPathsBetween(v1, v2);
265
+ let min = Infinity;
266
+ let minIndex = -1;
267
+ let index = 0;
268
+ for (const path of allPaths) {
269
+ const pathSumWeight = this.getPathSumWeight(path);
270
+ if (pathSumWeight < min) {
271
+ min = pathSumWeight;
272
+ minIndex = index;
273
+ }
274
+ index++;
275
+ }
276
+ return allPaths[minIndex] || null;
277
+ } else {
278
+ // BFS
279
+ let minPath: V[] = [];
280
+ const vertex1 = this.getVertex(v1);
281
+ const vertex2 = this.getVertex(v2);
282
+ if (!(vertex1 && vertex2)) {
283
+ return [];
284
+ }
285
+
286
+ const dfs = (cur: V, dest: V, visiting: Map<V, boolean>, path: V[]) => {
287
+ visiting.set(cur, true);
288
+
289
+ if (cur === dest) {
290
+ minPath = [vertex1, ...path];
291
+ return;
292
+ }
293
+
294
+ const neighbors = this.getNeighbors(cur);
295
+ for (const neighbor of neighbors) {
296
+ if (!visiting.get(neighbor)) {
297
+ path.push(neighbor);
298
+ dfs(neighbor, dest, visiting, path);
299
+ arrayRemove(path, vertex => vertex === neighbor);
300
+ }
301
+ }
302
+
303
+ visiting.set(cur, false);
304
+ };
305
+
306
+ dfs(vertex1, vertex2, new Map<V, boolean>(), []);
307
+ return minPath;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Dijkstra algorithm time: O(VE) space: O(V + E)
313
+ * @param src
314
+ * @param dest
315
+ * @param getMinDist
316
+ * @param genPaths
317
+ */
318
+ dijkstraWithoutHeap(src: V | VertexId, dest?: V | VertexId | null, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<V> {
319
+ if (getMinDist === undefined) getMinDist = false;
320
+ if (genPaths === undefined) genPaths = false;
321
+
322
+ if (dest === undefined) dest = null;
323
+ let minDist = Infinity;
324
+ let minDest: V | null = null;
325
+ let minPath: V[] = [];
326
+ const paths: V[][] = [];
327
+
328
+ const vertices = this._vertices;
329
+ const distMap: Map<V, number> = new Map();
330
+ const seen: Set<V> = new Set();
331
+ const preMap: Map<V, V | null> = new Map(); // predecessor
332
+ const srcVertex = this.getVertex(src);
333
+
334
+ const destVertex = dest ? this.getVertex(dest) : null;
335
+
336
+ if (!srcVertex) {
337
+ return null;
338
+ }
339
+
340
+ for (const vertex of vertices) {
341
+ distMap.set(vertex[1], Infinity);
342
+ }
343
+ distMap.set(srcVertex, 0);
344
+ preMap.set(srcVertex, null);
345
+
346
+ const getMinOfNoSeen = () => {
347
+ let min = Infinity;
348
+ let minV: V | null = null;
349
+ for (const [key, val] of distMap) {
350
+ if (!seen.has(key)) {
351
+ if (val < min) {
352
+ min = val;
353
+ minV = key;
354
+ }
355
+ }
356
+ }
357
+ return minV;
358
+ };
359
+
360
+ const getPaths = (minV: V | null) => {
361
+ for (const vertex of vertices) {
362
+ const path: V[] = [vertex[1]];
363
+ let parent = preMap.get(vertex[1]);
364
+ while (parent) {
365
+ path.push(parent);
366
+ parent = preMap.get(parent);
367
+ }
368
+ const reversed = path.reverse();
369
+ if (vertex[1] === minV) minPath = reversed;
370
+ paths.push(reversed);
371
+ }
372
+ };
373
+
374
+ for (let i = 1; i < vertices.size; i++) {
375
+ const cur = getMinOfNoSeen();
376
+ if (cur) {
377
+ seen.add(cur);
378
+ if (destVertex && destVertex === cur) {
379
+ if (getMinDist) {
380
+ minDist = distMap.get(destVertex) || Infinity;
381
+ }
382
+ if (genPaths) {
383
+ getPaths(destVertex);
384
+ }
385
+ return {distMap, preMap, seen, paths, minDist, minPath};
386
+ }
387
+ const neighbors = this.getNeighbors(cur);
388
+ for (const neighbor of neighbors) {
389
+ if (!seen.has(neighbor)) {
390
+ const edge = this.getEdge(cur, neighbor);
391
+ if (edge) {
392
+ const curFromMap = distMap.get(cur);
393
+ const neighborFromMap = distMap.get(neighbor);
394
+ // TODO after no-non-null-assertion not ensure the logic
395
+ if (curFromMap !== undefined && neighborFromMap !== undefined) {
396
+ if (edge.weight + curFromMap < neighborFromMap) {
397
+ distMap.set(neighbor, edge.weight + curFromMap);
398
+ preMap.set(neighbor, cur);
399
+ }
400
+ }
401
+
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
407
+
408
+ getMinDist && distMap.forEach((d, v) => {
409
+ if (v !== srcVertex) {
410
+ if (d < minDist) {
411
+ minDist = d;
412
+ if (genPaths) minDest = v;
413
+ }
414
+ }
415
+ });
416
+
417
+ genPaths && getPaths(minDest);
418
+
419
+ return {distMap, preMap, seen, paths, minDist, minPath};
420
+ }
421
+
422
+
423
+ /**
424
+ * Dijkstra algorithm time: O(logVE) space: O(V + E)
425
+ * @param src
426
+ * @param dest
427
+ * @param getMinDist
428
+ * @param genPaths
429
+ */
430
+ dijkstra(src: V | VertexId, dest?: V | VertexId | null, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<V> {
431
+ if (getMinDist === undefined) getMinDist = false;
432
+ if (genPaths === undefined) genPaths = false;
433
+
434
+ if (dest === undefined) dest = null;
435
+ let minDist = Infinity;
436
+ let minDest: V | null = null;
437
+ let minPath: V[] = [];
438
+ const paths: V[][] = [];
439
+ const vertices = this._vertices;
440
+ const distMap: Map<V, number> = new Map();
441
+ const seen: Set<V> = new Set();
442
+ const preMap: Map<V, V | null> = new Map(); // predecessor
443
+
444
+ const srcVertex = this.getVertex(src);
445
+ const destVertex = dest ? this.getVertex(dest) : null;
446
+
447
+ if (!srcVertex) {
448
+ return null;
449
+ }
450
+
451
+ for (const vertex of vertices) {
452
+ distMap.set(vertex[1], Infinity);
453
+ }
454
+
455
+ const heap = new PriorityQueue<{ id: number, val: V }>({comparator: (a, b) => a.id - b.id});
456
+ heap.offer({id: 0, val: srcVertex});
457
+
458
+ distMap.set(srcVertex, 0);
459
+ preMap.set(srcVertex, null);
460
+
461
+ const getPaths = (minV: V | null) => {
462
+ for (const vertex of vertices) {
463
+ const path: V[] = [vertex[1]];
464
+ let parent = preMap.get(vertex[1]);
465
+ while (parent) {
466
+ path.push(parent);
467
+ parent = preMap.get(parent);
468
+ }
469
+ const reversed = path.reverse();
470
+ if (vertex[1] === minV) minPath = reversed;
471
+ paths.push(reversed);
472
+ }
473
+ };
474
+
475
+ while (heap.size > 0) {
476
+ const curHeapNode = heap.poll();
477
+ const dist = curHeapNode?.id;
478
+ const cur = curHeapNode?.val;
479
+ if (dist !== undefined) {
480
+ if (cur) {
481
+ seen.add(cur);
482
+ if (destVertex && destVertex === cur) {
483
+ if (getMinDist) {
484
+ minDist = distMap.get(destVertex) || Infinity;
485
+ }
486
+ if (genPaths) {
487
+ getPaths(destVertex);
488
+ }
489
+ return {distMap, preMap, seen, paths, minDist, minPath};
490
+ }
491
+ const neighbors = this.getNeighbors(cur);
492
+ for (const neighbor of neighbors) {
493
+ if (!seen.has(neighbor)) {
494
+ const weight = this.getEdge(cur, neighbor)?.weight;
495
+ if (typeof weight === 'number') {
496
+ const distSrcToNeighbor = distMap.get(neighbor);
497
+ if (distSrcToNeighbor) {
498
+ if (dist + weight < distSrcToNeighbor) {
499
+ heap.offer({id: dist + weight, val: neighbor});
500
+ preMap.set(neighbor, cur);
501
+ distMap.set(neighbor, dist + weight);
502
+ }
503
+ }
504
+ }
505
+ }
506
+ }
507
+ }
508
+ }
509
+ }
510
+
511
+
512
+ if (getMinDist) {
513
+ distMap.forEach((d, v) => {
514
+ if (v !== srcVertex) {
515
+ if (d < minDist) {
516
+ minDist = d;
517
+ if (genPaths) minDest = v;
518
+ }
519
+ }
520
+ });
521
+ }
522
+
523
+
524
+ if (genPaths) {
525
+ getPaths(minDest);
526
+ }
527
+
528
+
529
+ return {distMap, preMap, seen, paths, minDist, minPath};
530
+ }
531
+
532
+ abstract getEndsOfEdge(edge: E): [V, V] | null;
533
+
534
+
535
+ /**
536
+ * BellmanFord time:O(VE) space:O(V)
537
+ * one to rest pairs
538
+ * @param src
539
+ * @param scanNegativeCycle
540
+ * @param getMin
541
+ * @param genPath
542
+ */
543
+ bellmanFord(src: V | VertexId, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean) {
544
+ if (getMin === undefined) getMin = false;
545
+ if (genPath === undefined) genPath = false;
546
+
547
+ const srcVertex = this.getVertex(src);
548
+ const paths: V[][] = [];
549
+ const distMap: Map<V, number> = new Map();
550
+ const preMap: Map<V, V> = new Map(); // predecessor
551
+ let min = Infinity;
552
+ let minPath: V[] = [];
553
+ // TODO
554
+ let hasNegativeCycle: boolean | undefined = undefined;
555
+ if (scanNegativeCycle) hasNegativeCycle = false;
556
+ if (!srcVertex) return {hasNegativeCycle, distMap, preMap, paths, min, minPath};
557
+
558
+ const vertices = this._vertices;
559
+ const numOfVertices = vertices.size;
560
+ const edges = this.edgeSet();
561
+ const numOfEdges = edges.length;
562
+
563
+ this._vertices.forEach(vertex => {
564
+ distMap.set(vertex, Infinity);
565
+ });
566
+
567
+ distMap.set(srcVertex, 0);
568
+
569
+ for (let i = 1; i < numOfVertices; ++i) {
570
+ for (let j = 0; j < numOfEdges; ++j) {
571
+ const ends = this.getEndsOfEdge(edges[j]);
572
+ if (ends) {
573
+ const [s, d] = ends;
574
+ const weight = edges[j].weight;
575
+ const sWeight = distMap.get(s);
576
+ const dWeight = distMap.get(d);
577
+ if (sWeight !== undefined && dWeight !== undefined) {
578
+ if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) {
579
+ distMap.set(d, sWeight + weight);
580
+ genPath && preMap.set(d, s);
581
+ }
582
+ }
583
+ }
584
+ }
585
+ }
586
+
587
+ let minDest: V | null = null;
588
+ if (getMin) {
589
+ distMap.forEach((d, v) => {
590
+ if (v !== srcVertex) {
591
+ if (d < min) {
592
+ min = d;
593
+ if (genPath) minDest = v;
594
+ }
595
+ }
596
+ });
597
+ }
598
+
599
+ if (genPath) {
600
+ for (const vertex of vertices) {
601
+ const path: V[] = [vertex[1]];
602
+ let parent = preMap.get(vertex[1]);
603
+ while (parent !== undefined) {
604
+ path.push(parent);
605
+ parent = preMap.get(parent);
606
+ }
607
+ const reversed = path.reverse();
608
+ if (vertex[1] === minDest) minPath = reversed;
609
+ paths.push(reversed);
610
+ }
611
+ }
612
+
613
+ for (let j = 0; j < numOfEdges; ++j) {
614
+ const ends = this.getEndsOfEdge(edges[j]);
615
+ if (ends) {
616
+ const [s] = ends;
617
+ const weight = edges[j].weight;
618
+ const sWeight = distMap.get(s);
619
+ if (sWeight) {
620
+ if (sWeight !== Infinity && sWeight + weight < sWeight) hasNegativeCycle = true;
621
+ }
622
+ }
623
+ }
624
+
625
+ return {hasNegativeCycle, distMap, preMap, paths, min, minPath};
626
+ }
627
+
628
+ /**
629
+ * Floyd algorithm time: O(V^3) space: O(V^2), not support graph with negative weight cycle
630
+ * all pairs
631
+ */
632
+ floyd(): { costs: number[][], predecessor: (V | null)[][] } {
633
+ const idAndVertices = [...this._vertices];
634
+ const n = idAndVertices.length;
635
+
636
+ const costs: number[][] = [];
637
+ const predecessor: (V | null)[][] = [];
638
+ // successors
639
+
640
+ for (let i = 0; i < n; i++) {
641
+ costs[i] = [];
642
+ predecessor[i] = [];
643
+ for (let j = 0; j < n; j++) {
644
+ predecessor[i][j] = null;
645
+ }
646
+ }
647
+
648
+ for (let i = 0; i < n; i++) {
649
+ for (let j = 0; j < n; j++) {
650
+ costs[i][j] = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])?.weight || Infinity;
651
+ }
652
+ }
653
+
654
+ for (let k = 0; k < n; k++) {
655
+ for (let i = 0; i < n; i++) {
656
+ for (let j = 0; j < n; j++) {
657
+ if (costs[i][j] > costs[i][k] + costs[k][j]) {
658
+ costs[i][j] = costs[i][k] + costs[k][j];
659
+ predecessor[i][j] = idAndVertices[k][1];
660
+ }
661
+ }
662
+ }
663
+ }
664
+ return {costs, predecessor};
665
+
666
+ }
667
+
668
+
669
+ /**--- start find cycles --- */
670
+
671
+ /**
672
+ * Tarjan is an algorithm based on DFS,which is used to solve the connectivity problem of graphs.
673
+ * Tarjan can find cycles in directed or undirected graph
674
+ * Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,
675
+ * Tarjan solve the bi-connected components of undirected graphs;
676
+ * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.
677
+ */
678
+ tarjan(needArticulationPoints?: boolean, needBridges?: boolean, needSCCs?: boolean, needCycles?: boolean) {
679
+ // !! in undirected graph we will not let child visit parent when DFS
680
+ // !! articulation point(in DFS search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)
681
+ // !! bridge: low(child) > dfn(cur)
682
+
683
+ const defaultConfig = false;
684
+ if (needArticulationPoints === undefined) needArticulationPoints = defaultConfig;
685
+ if (needBridges === undefined) needBridges = defaultConfig;
686
+ if (needSCCs === undefined) needSCCs = defaultConfig;
687
+ if (needCycles === undefined) needCycles = defaultConfig;
688
+
689
+ const dfnMap: Map<V, number> = new Map();
690
+ const lowMap: Map<V, number> = new Map();
691
+ const vertices = this._vertices;
692
+ vertices.forEach(v => {
693
+ dfnMap.set(v, -1);
694
+ lowMap.set(v, Infinity);
695
+ });
696
+
697
+ const [root] = vertices.values();
698
+
699
+ const articulationPoints: V[] = [];
700
+ const bridges: E[] = [];
701
+ let dfn = 0;
702
+ const dfs = (cur: V, parent: V | null) => {
703
+ dfn++;
704
+ dfnMap.set(cur, dfn);
705
+ lowMap.set(cur, dfn);
706
+
707
+ const neighbors = this.getNeighbors(cur);
708
+ let childCount = 0; // child in DFS tree not child in graph
709
+ for (const neighbor of neighbors) {
710
+ if (neighbor !== parent) {
711
+ if (dfnMap.get(neighbor) === -1) {
712
+ childCount++;
713
+ dfs(neighbor, cur);
714
+ }
715
+ const childLow = lowMap.get(neighbor);
716
+ const curLow = lowMap.get(cur);
717
+ // TODO after no-non-null-assertion not ensure the logic
718
+ if (curLow !== undefined && childLow !== undefined) {
719
+ lowMap.set(cur, Math.min(curLow, childLow));
720
+ }
721
+ const curFromMap = dfnMap.get(cur);
722
+ if (childLow !== undefined && curFromMap !== undefined) {
723
+ if (needArticulationPoints) {
724
+ if ((cur === root && childCount >= 2) || ((cur !== root) && (childLow >= curFromMap))) {
725
+ // todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {
726
+ articulationPoints.push(cur);
727
+ }
728
+ }
729
+
730
+ if (needBridges) {
731
+ if (childLow > curFromMap) {
732
+ const edgeCurToNeighbor = this.getEdge(cur, neighbor);
733
+ if (edgeCurToNeighbor) {
734
+ bridges.push(edgeCurToNeighbor);
735
+ }
736
+ }
737
+ }
738
+ }
739
+ }
740
+ }
741
+
742
+ };
743
+
744
+ dfs(root, null);
745
+
746
+ let SCCs: Map<number, V[]> = new Map();
747
+
748
+ const getSCCs = () => {
749
+ const SCCs: Map<number, V[]> = new Map();
750
+ lowMap.forEach((low, vertex) => {
751
+ if (!SCCs.has(low)) {
752
+ SCCs.set(low, [vertex]);
753
+ } else {
754
+ SCCs.get(low)?.push(vertex);
755
+ }
756
+ });
757
+ return SCCs;
758
+ };
759
+
760
+ if (needSCCs) {
761
+ SCCs = getSCCs();
762
+ }
763
+
764
+ const cycles: Map<number, V[]> = new Map();
765
+ if (needCycles) {
766
+ let SCCs: Map<number, V[]> = new Map();
767
+ if (SCCs.size < 1) {
768
+ SCCs = getSCCs();
769
+ }
770
+
771
+ SCCs.forEach((SCC, low) => {
772
+ if (SCC.length > 1) {
773
+ cycles.set(low, SCC);
774
+ }
775
+ });
776
+ }
777
+
778
+ return {dfnMap, lowMap, bridges, articulationPoints, SCCs, cycles};
779
+ }
780
+
781
+
782
+ // unionFind() {
783
+ // }
784
+
785
+ /**--- end find cycles --- */
786
+
787
+
788
+ // Minimum Spanning Tree
789
+ }