tree-set-typed 2.3.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.
Files changed (273) hide show
  1. package/.eslintrc.js +61 -0
  2. package/.prettierignore +6 -0
  3. package/.prettierrc.js +16 -0
  4. package/LICENSE +21 -0
  5. package/README.md +482 -0
  6. package/coverage/clover.xml +13 -0
  7. package/coverage/coverage-final.json +96 -0
  8. package/coverage/coverage-summary.json +60 -0
  9. package/coverage/lcov-report/base.css +403 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +119 -0
  13. package/coverage/lcov-report/index.ts.html +109 -0
  14. package/coverage/lcov-report/prettify.css +1 -0
  15. package/coverage/lcov-report/prettify.js +2 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +206 -0
  18. package/coverage/lcov.info +14 -0
  19. package/dist/cjs/index.cjs +12 -0
  20. package/dist/cjs/index.cjs.map +1 -0
  21. package/dist/cjs-legacy/index.cjs +12 -0
  22. package/dist/cjs-legacy/index.cjs.map +1 -0
  23. package/dist/esm/index.mjs +3 -0
  24. package/dist/esm/index.mjs.map +1 -0
  25. package/dist/esm-legacy/index.mjs +3 -0
  26. package/dist/esm-legacy/index.mjs.map +1 -0
  27. package/dist/types/common/index.d.ts +12 -0
  28. package/dist/types/constants/index.d.ts +4 -0
  29. package/dist/types/data-structures/base/index.d.ts +2 -0
  30. package/dist/types/data-structures/base/iterable-element-base.d.ts +219 -0
  31. package/dist/types/data-structures/base/iterable-entry-base.d.ts +150 -0
  32. package/dist/types/data-structures/base/linear-base.d.ts +335 -0
  33. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +236 -0
  34. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +197 -0
  35. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +440 -0
  36. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +174 -0
  37. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +807 -0
  38. package/dist/types/data-structures/binary-tree/bst.d.ts +645 -0
  39. package/dist/types/data-structures/binary-tree/index.d.ts +10 -0
  40. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +312 -0
  41. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +160 -0
  42. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +243 -0
  43. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +333 -0
  44. package/dist/types/data-structures/graph/abstract-graph.d.ts +340 -0
  45. package/dist/types/data-structures/graph/directed-graph.d.ts +332 -0
  46. package/dist/types/data-structures/graph/index.d.ts +4 -0
  47. package/dist/types/data-structures/graph/map-graph.d.ts +78 -0
  48. package/dist/types/data-structures/graph/undirected-graph.d.ts +347 -0
  49. package/dist/types/data-structures/hash/hash-map.d.ts +428 -0
  50. package/dist/types/data-structures/hash/index.d.ts +1 -0
  51. package/dist/types/data-structures/heap/heap.d.ts +552 -0
  52. package/dist/types/data-structures/heap/index.d.ts +3 -0
  53. package/dist/types/data-structures/heap/max-heap.d.ts +32 -0
  54. package/dist/types/data-structures/heap/min-heap.d.ts +33 -0
  55. package/dist/types/data-structures/index.d.ts +12 -0
  56. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +437 -0
  57. package/dist/types/data-structures/linked-list/index.d.ts +3 -0
  58. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +567 -0
  59. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +27 -0
  60. package/dist/types/data-structures/matrix/index.d.ts +2 -0
  61. package/dist/types/data-structures/matrix/matrix.d.ts +168 -0
  62. package/dist/types/data-structures/matrix/navigator.d.ts +55 -0
  63. package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
  64. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +27 -0
  65. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +26 -0
  66. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +15 -0
  67. package/dist/types/data-structures/queue/deque.d.ts +459 -0
  68. package/dist/types/data-structures/queue/index.d.ts +2 -0
  69. package/dist/types/data-structures/queue/queue.d.ts +364 -0
  70. package/dist/types/data-structures/stack/index.d.ts +1 -0
  71. package/dist/types/data-structures/stack/stack.d.ts +324 -0
  72. package/dist/types/data-structures/tree/index.d.ts +1 -0
  73. package/dist/types/data-structures/tree/tree.d.ts +62 -0
  74. package/dist/types/data-structures/trie/index.d.ts +1 -0
  75. package/dist/types/data-structures/trie/trie.d.ts +412 -0
  76. package/dist/types/index.d.ts +23 -0
  77. package/dist/types/interfaces/binary-tree.d.ts +60 -0
  78. package/dist/types/interfaces/doubly-linked-list.d.ts +1 -0
  79. package/dist/types/interfaces/graph.d.ts +21 -0
  80. package/dist/types/interfaces/heap.d.ts +1 -0
  81. package/dist/types/interfaces/index.d.ts +8 -0
  82. package/dist/types/interfaces/navigator.d.ts +1 -0
  83. package/dist/types/interfaces/priority-queue.d.ts +1 -0
  84. package/dist/types/interfaces/segment-tree.d.ts +1 -0
  85. package/dist/types/interfaces/singly-linked-list.d.ts +1 -0
  86. package/dist/types/types/common.d.ts +15 -0
  87. package/dist/types/types/data-structures/base/base.d.ts +13 -0
  88. package/dist/types/types/data-structures/base/index.d.ts +1 -0
  89. package/dist/types/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
  90. package/dist/types/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -0
  91. package/dist/types/types/data-structures/binary-tree/avl-tree.d.ts +2 -0
  92. package/dist/types/types/data-structures/binary-tree/binary-indexed-tree.d.ts +1 -0
  93. package/dist/types/types/data-structures/binary-tree/binary-tree.d.ts +29 -0
  94. package/dist/types/types/data-structures/binary-tree/bst.d.ts +12 -0
  95. package/dist/types/types/data-structures/binary-tree/index.d.ts +9 -0
  96. package/dist/types/types/data-structures/binary-tree/red-black-tree.d.ts +3 -0
  97. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -0
  98. package/dist/types/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
  99. package/dist/types/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -0
  100. package/dist/types/types/data-structures/graph/abstract-graph.d.ts +14 -0
  101. package/dist/types/types/data-structures/graph/directed-graph.d.ts +1 -0
  102. package/dist/types/types/data-structures/graph/index.d.ts +3 -0
  103. package/dist/types/types/data-structures/graph/map-graph.d.ts +1 -0
  104. package/dist/types/types/data-structures/graph/undirected-graph.d.ts +1 -0
  105. package/dist/types/types/data-structures/hash/hash-map.d.ts +19 -0
  106. package/dist/types/types/data-structures/hash/index.d.ts +2 -0
  107. package/dist/types/types/data-structures/heap/heap.d.ts +5 -0
  108. package/dist/types/types/data-structures/heap/index.d.ts +1 -0
  109. package/dist/types/types/data-structures/heap/max-heap.d.ts +1 -0
  110. package/dist/types/types/data-structures/heap/min-heap.d.ts +1 -0
  111. package/dist/types/types/data-structures/index.d.ts +12 -0
  112. package/dist/types/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -0
  113. package/dist/types/types/data-structures/linked-list/index.d.ts +3 -0
  114. package/dist/types/types/data-structures/linked-list/singly-linked-list.d.ts +2 -0
  115. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +4 -0
  116. package/dist/types/types/data-structures/matrix/index.d.ts +2 -0
  117. package/dist/types/types/data-structures/matrix/matrix.d.ts +7 -0
  118. package/dist/types/types/data-structures/matrix/navigator.d.ts +14 -0
  119. package/dist/types/types/data-structures/priority-queue/index.d.ts +3 -0
  120. package/dist/types/types/data-structures/priority-queue/max-priority-queue.d.ts +1 -0
  121. package/dist/types/types/data-structures/priority-queue/min-priority-queue.d.ts +1 -0
  122. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +2 -0
  123. package/dist/types/types/data-structures/queue/deque.d.ts +4 -0
  124. package/dist/types/types/data-structures/queue/index.d.ts +2 -0
  125. package/dist/types/types/data-structures/queue/queue.d.ts +4 -0
  126. package/dist/types/types/data-structures/stack/index.d.ts +1 -0
  127. package/dist/types/types/data-structures/stack/stack.d.ts +2 -0
  128. package/dist/types/types/data-structures/tree/index.d.ts +1 -0
  129. package/dist/types/types/data-structures/tree/tree.d.ts +1 -0
  130. package/dist/types/types/data-structures/trie/index.d.ts +1 -0
  131. package/dist/types/types/data-structures/trie/trie.d.ts +4 -0
  132. package/dist/types/types/index.d.ts +3 -0
  133. package/dist/types/types/utils/index.d.ts +2 -0
  134. package/dist/types/types/utils/utils.d.ts +22 -0
  135. package/dist/types/types/utils/validate-type.d.ts +19 -0
  136. package/dist/types/utils/index.d.ts +2 -0
  137. package/dist/types/utils/number.d.ts +14 -0
  138. package/dist/types/utils/utils.d.ts +209 -0
  139. package/dist/umd/red-black-tree-typed.js +14578 -0
  140. package/dist/umd/red-black-tree-typed.js.map +1 -0
  141. package/dist/umd/red-black-tree-typed.min.js +44 -0
  142. package/dist/umd/red-black-tree-typed.min.js.map +1 -0
  143. package/docs/.nojekyll +1 -0
  144. package/docs/assets/highlight.css +92 -0
  145. package/docs/assets/main.js +59 -0
  146. package/docs/assets/navigation.js +1 -0
  147. package/docs/assets/search.js +1 -0
  148. package/docs/assets/style.css +1383 -0
  149. package/docs/classes/AVLTree.html +2046 -0
  150. package/docs/classes/AVLTreeNode.html +263 -0
  151. package/docs/index.html +523 -0
  152. package/docs/modules.html +45 -0
  153. package/jest.config.js +8 -0
  154. package/package.json +113 -0
  155. package/src/common/index.ts +23 -0
  156. package/src/constants/index.ts +4 -0
  157. package/src/data-structures/base/index.ts +2 -0
  158. package/src/data-structures/base/iterable-element-base.ts +352 -0
  159. package/src/data-structures/base/iterable-entry-base.ts +246 -0
  160. package/src/data-structures/base/linear-base.ts +643 -0
  161. package/src/data-structures/binary-tree/avl-tree-counter.ts +539 -0
  162. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +438 -0
  163. package/src/data-structures/binary-tree/avl-tree.ts +840 -0
  164. package/src/data-structures/binary-tree/binary-indexed-tree.ts +331 -0
  165. package/src/data-structures/binary-tree/binary-tree.ts +2492 -0
  166. package/src/data-structures/binary-tree/bst.ts +2024 -0
  167. package/src/data-structures/binary-tree/index.ts +10 -0
  168. package/src/data-structures/binary-tree/red-black-tree.ts +767 -0
  169. package/src/data-structures/binary-tree/segment-tree.ts +324 -0
  170. package/src/data-structures/binary-tree/tree-counter.ts +575 -0
  171. package/src/data-structures/binary-tree/tree-multi-map.ts +549 -0
  172. package/src/data-structures/graph/abstract-graph.ts +1081 -0
  173. package/src/data-structures/graph/directed-graph.ts +715 -0
  174. package/src/data-structures/graph/index.ts +4 -0
  175. package/src/data-structures/graph/map-graph.ts +132 -0
  176. package/src/data-structures/graph/undirected-graph.ts +626 -0
  177. package/src/data-structures/hash/hash-map.ts +813 -0
  178. package/src/data-structures/hash/index.ts +1 -0
  179. package/src/data-structures/heap/heap.ts +1020 -0
  180. package/src/data-structures/heap/index.ts +3 -0
  181. package/src/data-structures/heap/max-heap.ts +47 -0
  182. package/src/data-structures/heap/min-heap.ts +36 -0
  183. package/src/data-structures/index.ts +12 -0
  184. package/src/data-structures/linked-list/doubly-linked-list.ts +876 -0
  185. package/src/data-structures/linked-list/index.ts +3 -0
  186. package/src/data-structures/linked-list/singly-linked-list.ts +1050 -0
  187. package/src/data-structures/linked-list/skip-linked-list.ts +173 -0
  188. package/src/data-structures/matrix/index.ts +2 -0
  189. package/src/data-structures/matrix/matrix.ts +491 -0
  190. package/src/data-structures/matrix/navigator.ts +124 -0
  191. package/src/data-structures/priority-queue/index.ts +3 -0
  192. package/src/data-structures/priority-queue/max-priority-queue.ts +42 -0
  193. package/src/data-structures/priority-queue/min-priority-queue.ts +29 -0
  194. package/src/data-structures/priority-queue/priority-queue.ts +19 -0
  195. package/src/data-structures/queue/deque.ts +1001 -0
  196. package/src/data-structures/queue/index.ts +2 -0
  197. package/src/data-structures/queue/queue.ts +592 -0
  198. package/src/data-structures/stack/index.ts +1 -0
  199. package/src/data-structures/stack/stack.ts +469 -0
  200. package/src/data-structures/tree/index.ts +1 -0
  201. package/src/data-structures/tree/tree.ts +115 -0
  202. package/src/data-structures/trie/index.ts +1 -0
  203. package/src/data-structures/trie/trie.ts +756 -0
  204. package/src/index.ts +24 -0
  205. package/src/interfaces/binary-tree.ts +252 -0
  206. package/src/interfaces/doubly-linked-list.ts +1 -0
  207. package/src/interfaces/graph.ts +44 -0
  208. package/src/interfaces/heap.ts +1 -0
  209. package/src/interfaces/index.ts +8 -0
  210. package/src/interfaces/navigator.ts +1 -0
  211. package/src/interfaces/priority-queue.ts +1 -0
  212. package/src/interfaces/segment-tree.ts +1 -0
  213. package/src/interfaces/singly-linked-list.ts +1 -0
  214. package/src/types/common.ts +25 -0
  215. package/src/types/data-structures/base/base.ts +34 -0
  216. package/src/types/data-structures/base/index.ts +1 -0
  217. package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
  218. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +3 -0
  219. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -0
  220. package/src/types/data-structures/binary-tree/binary-indexed-tree.ts +1 -0
  221. package/src/types/data-structures/binary-tree/binary-tree.ts +31 -0
  222. package/src/types/data-structures/binary-tree/bst.ts +19 -0
  223. package/src/types/data-structures/binary-tree/index.ts +9 -0
  224. package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
  225. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -0
  226. package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
  227. package/src/types/data-structures/binary-tree/tree-multi-map.ts +3 -0
  228. package/src/types/data-structures/graph/abstract-graph.ts +18 -0
  229. package/src/types/data-structures/graph/directed-graph.ts +2 -0
  230. package/src/types/data-structures/graph/index.ts +3 -0
  231. package/src/types/data-structures/graph/map-graph.ts +1 -0
  232. package/src/types/data-structures/graph/undirected-graph.ts +1 -0
  233. package/src/types/data-structures/hash/hash-map.ts +19 -0
  234. package/src/types/data-structures/hash/index.ts +3 -0
  235. package/src/types/data-structures/heap/heap.ts +6 -0
  236. package/src/types/data-structures/heap/index.ts +1 -0
  237. package/src/types/data-structures/heap/max-heap.ts +1 -0
  238. package/src/types/data-structures/heap/min-heap.ts +1 -0
  239. package/src/types/data-structures/index.ts +12 -0
  240. package/src/types/data-structures/linked-list/doubly-linked-list.ts +3 -0
  241. package/src/types/data-structures/linked-list/index.ts +3 -0
  242. package/src/types/data-structures/linked-list/singly-linked-list.ts +3 -0
  243. package/src/types/data-structures/linked-list/skip-linked-list.ts +1 -0
  244. package/src/types/data-structures/matrix/index.ts +2 -0
  245. package/src/types/data-structures/matrix/matrix.ts +7 -0
  246. package/src/types/data-structures/matrix/navigator.ts +14 -0
  247. package/src/types/data-structures/priority-queue/index.ts +3 -0
  248. package/src/types/data-structures/priority-queue/max-priority-queue.ts +1 -0
  249. package/src/types/data-structures/priority-queue/min-priority-queue.ts +1 -0
  250. package/src/types/data-structures/priority-queue/priority-queue.ts +3 -0
  251. package/src/types/data-structures/queue/deque.ts +5 -0
  252. package/src/types/data-structures/queue/index.ts +2 -0
  253. package/src/types/data-structures/queue/queue.ts +5 -0
  254. package/src/types/data-structures/stack/index.ts +1 -0
  255. package/src/types/data-structures/stack/stack.ts +3 -0
  256. package/src/types/data-structures/tree/index.ts +1 -0
  257. package/src/types/data-structures/tree/tree.ts +1 -0
  258. package/src/types/data-structures/trie/index.ts +1 -0
  259. package/src/types/data-structures/trie/trie.ts +3 -0
  260. package/src/types/index.ts +3 -0
  261. package/src/types/utils/index.ts +2 -0
  262. package/src/types/utils/utils.ts +33 -0
  263. package/src/types/utils/validate-type.ts +35 -0
  264. package/src/utils/index.ts +2 -0
  265. package/src/utils/number.ts +22 -0
  266. package/src/utils/utils.ts +350 -0
  267. package/test/index.test.ts +111 -0
  268. package/tsconfig.base.json +23 -0
  269. package/tsconfig.json +12 -0
  270. package/tsconfig.test.json +8 -0
  271. package/tsconfig.types.json +15 -0
  272. package/tsup.config.js +28 -0
  273. package/tsup.node.config.js +71 -0
@@ -0,0 +1,626 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
8
+
9
+ import type { GraphOptions, VertexKey } from '../../types';
10
+ import { IGraph } from '../../interfaces';
11
+ import { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';
12
+ import { arrayRemove } from '../../utils';
13
+
14
+ export class UndirectedVertex<V = any> extends AbstractVertex<V> {
15
+ constructor(key: VertexKey, value?: V) {
16
+ super(key, value);
17
+ }
18
+ }
19
+
20
+ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
21
+ endpoints: [VertexKey, VertexKey];
22
+
23
+ constructor(v1: VertexKey, v2: VertexKey, weight?: number, value?: E) {
24
+ super(weight, value);
25
+ this.endpoints = [v1, v2];
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Undirected graph implementation.
31
+ * @template V - Vertex value type.
32
+ * @template E - Edge value type.
33
+ * @template VO - Concrete vertex class (extends AbstractVertex<V>).
34
+ * @template EO - Concrete edge class (extends AbstractEdge<E>).
35
+ * @remarks Time O(1), Space O(1)
36
+ * @example
37
+ * // basic UndirectedGraph vertex and edge creation
38
+ * // Create a simple undirected graph
39
+ * const graph = new UndirectedGraph<string>();
40
+ *
41
+ * // Add vertices
42
+ * graph.addVertex('A');
43
+ * graph.addVertex('B');
44
+ * graph.addVertex('C');
45
+ * graph.addVertex('D');
46
+ *
47
+ * // Verify vertices exist
48
+ * console.log(graph.hasVertex('A')); // true;
49
+ * console.log(graph.hasVertex('B')); // true;
50
+ * console.log(graph.hasVertex('E')); // false;
51
+ *
52
+ * // Check vertex count
53
+ * console.log(graph.size); // 4;
54
+ * @example
55
+ * // UndirectedGraph edge operations (bidirectional)
56
+ * const graph = new UndirectedGraph<string>();
57
+ *
58
+ * // Add vertices
59
+ * graph.addVertex('A');
60
+ * graph.addVertex('B');
61
+ * graph.addVertex('C');
62
+ *
63
+ * // Add undirected edges (both directions automatically)
64
+ * graph.addEdge('A', 'B', 1);
65
+ * graph.addEdge('B', 'C', 2);
66
+ * graph.addEdge('A', 'C', 3);
67
+ *
68
+ * // Verify edges exist in both directions
69
+ * console.log(graph.hasEdge('A', 'B')); // true;
70
+ * console.log(graph.hasEdge('B', 'A')); // true; // Bidirectional!
71
+ *
72
+ * console.log(graph.hasEdge('C', 'B')); // true;
73
+ * console.log(graph.hasEdge('B', 'C')); // true; // Bidirectional!
74
+ *
75
+ * // Get neighbors of A
76
+ * const neighborsA = graph.getNeighbors('A');
77
+ * console.log(neighborsA[0].key); // 'B';
78
+ * console.log(neighborsA[1].key); // 'C';
79
+ * @example
80
+ * // UndirectedGraph deleteEdge and vertex operations
81
+ * const graph = new UndirectedGraph<string>();
82
+ *
83
+ * // Build a simple undirected graph
84
+ * graph.addVertex('X');
85
+ * graph.addVertex('Y');
86
+ * graph.addVertex('Z');
87
+ * graph.addEdge('X', 'Y', 1);
88
+ * graph.addEdge('Y', 'Z', 2);
89
+ * graph.addEdge('X', 'Z', 3);
90
+ *
91
+ * // Delete an edge
92
+ * graph.deleteEdge('X', 'Y');
93
+ * console.log(graph.hasEdge('X', 'Y')); // false;
94
+ *
95
+ * // Bidirectional deletion confirmed
96
+ * console.log(graph.hasEdge('Y', 'X')); // false;
97
+ *
98
+ * // Other edges should remain
99
+ * console.log(graph.hasEdge('Y', 'Z')); // true;
100
+ * console.log(graph.hasEdge('Z', 'Y')); // true;
101
+ *
102
+ * // Delete a vertex
103
+ * graph.deleteVertex('Y');
104
+ * console.log(graph.hasVertex('Y')); // false;
105
+ * console.log(graph.size); // 2;
106
+ * @example
107
+ * // UndirectedGraph connectivity and neighbors
108
+ * const graph = new UndirectedGraph<string>();
109
+ *
110
+ * // Build a friendship network
111
+ * const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
112
+ * for (const person of people) {
113
+ * graph.addVertex(person);
114
+ * }
115
+ *
116
+ * // Add friendships (undirected edges)
117
+ * graph.addEdge('Alice', 'Bob', 1);
118
+ * graph.addEdge('Alice', 'Charlie', 1);
119
+ * graph.addEdge('Bob', 'Diana', 1);
120
+ * graph.addEdge('Charlie', 'Eve', 1);
121
+ * graph.addEdge('Diana', 'Eve', 1);
122
+ *
123
+ * // Get friends of each person
124
+ * const aliceFriends = graph.getNeighbors('Alice');
125
+ * console.log(aliceFriends[0].key); // 'Bob';
126
+ * console.log(aliceFriends[1].key); // 'Charlie';
127
+ * console.log(aliceFriends.length); // 2;
128
+ *
129
+ * const dianaFriends = graph.getNeighbors('Diana');
130
+ * console.log(dianaFriends[0].key); // 'Bob';
131
+ * console.log(dianaFriends[1].key); // 'Eve';
132
+ * console.log(dianaFriends.length); // 2;
133
+ *
134
+ * // Verify bidirectional friendship
135
+ * const bobFriends = graph.getNeighbors('Bob');
136
+ * console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
137
+ * console.log(bobFriends[1].key); // 'Diana';
138
+ * @example
139
+ * // UndirectedGraph for social network connectivity analysis
140
+ * interface Person {
141
+ * id: number;
142
+ * name: string;
143
+ * location: string;
144
+ * }
145
+ *
146
+ * // UndirectedGraph is perfect for modeling symmetric relationships
147
+ * // (friendships, collaborations, partnerships)
148
+ * const socialNetwork = new UndirectedGraph<number, Person>();
149
+ *
150
+ * // Add people as vertices
151
+ * const people: [number, Person][] = [
152
+ * [1, { id: 1, name: 'Alice', location: 'New York' }],
153
+ * [2, { id: 2, name: 'Bob', location: 'San Francisco' }],
154
+ * [3, { id: 3, name: 'Charlie', location: 'Boston' }],
155
+ * [4, { id: 4, name: 'Diana', location: 'New York' }],
156
+ * [5, { id: 5, name: 'Eve', location: 'Seattle' }]
157
+ * ];
158
+ *
159
+ * for (const [id] of people) {
160
+ * socialNetwork.addVertex(id);
161
+ * }
162
+ *
163
+ * // Add friendships (automatically bidirectional)
164
+ * socialNetwork.addEdge(1, 2, 1); // Alice <-> Bob
165
+ * socialNetwork.addEdge(1, 3, 1); // Alice <-> Charlie
166
+ * socialNetwork.addEdge(2, 4, 1); // Bob <-> Diana
167
+ * socialNetwork.addEdge(3, 5, 1); // Charlie <-> Eve
168
+ * socialNetwork.addEdge(4, 5, 1); // Diana <-> Eve
169
+ *
170
+ * console.log(socialNetwork.size); // 5;
171
+ *
172
+ * // Find direct connections for Alice
173
+ * const aliceConnections = socialNetwork.getNeighbors(1);
174
+ * console.log(aliceConnections[0].key); // 2;
175
+ * console.log(aliceConnections[1].key); // 3;
176
+ * console.log(aliceConnections.length); // 2;
177
+ *
178
+ * // Verify bidirectional connections
179
+ * console.log(socialNetwork.hasEdge(1, 2)); // true;
180
+ * console.log(socialNetwork.hasEdge(2, 1)); // true; // Friendship works both ways!
181
+ *
182
+ * // Remove a person from network
183
+ * socialNetwork.deleteVertex(2); // Bob leaves
184
+ * console.log(socialNetwork.hasVertex(2)); // false;
185
+ * console.log(socialNetwork.size); // 4;
186
+ *
187
+ * // Alice loses Bob as a friend
188
+ * const updatedAliceConnections = socialNetwork.getNeighbors(1);
189
+ * console.log(updatedAliceConnections[0].key); // 3;
190
+ * console.log(updatedAliceConnections[1]); // undefined;
191
+ *
192
+ * // Diana loses Bob as a friend
193
+ * const dianaConnections = socialNetwork.getNeighbors(4);
194
+ * console.log(dianaConnections[0].key); // 5;
195
+ * console.log(dianaConnections[1]); // undefined;
196
+ */
197
+ export class UndirectedGraph<
198
+ V = any,
199
+ E = any,
200
+ VO extends UndirectedVertex<V> = UndirectedVertex<V>,
201
+ EO extends UndirectedEdge<E> = UndirectedEdge<E>
202
+ >
203
+ extends AbstractGraph<V, E, VO, EO>
204
+ implements IGraph<V, E, VO, EO>
205
+ {
206
+ /**
207
+ * Construct an undirected graph with runtime defaults.
208
+ * @param options - `GraphOptions<V>` (e.g. `vertexValueInitializer`, `defaultEdgeWeight`).
209
+ * @remarks Time O(1), Space O(1)
210
+ */
211
+ constructor(options?: Partial<GraphOptions<V>>) {
212
+ super(options);
213
+ this._edgeMap = new Map<VO, EO[]>();
214
+ }
215
+
216
+ protected _edgeMap: Map<VO, EO[]>;
217
+
218
+ get edgeMap(): Map<VO, EO[]> {
219
+ return this._edgeMap;
220
+ }
221
+
222
+ set edgeMap(v: Map<VO, EO[]>) {
223
+ this._edgeMap = v;
224
+ }
225
+
226
+ /**
227
+ * Construct an undirected graph from keys with value initializer `v => v`.
228
+ * @template K - Vertex key type.
229
+ * @param keys - Iterable of vertex keys.
230
+ * @returns UndirectedGraph with all keys added.
231
+ * @remarks Time O(V), Space O(V)
232
+ */
233
+ static fromKeys<K extends VertexKey>(
234
+ keys: Iterable<K>
235
+ ): UndirectedGraph<K, any, UndirectedVertex<K>, UndirectedEdge<any>> {
236
+ const g: UndirectedGraph<K, any, UndirectedVertex<K>, UndirectedEdge<any>> = new UndirectedGraph<K, any>({
237
+ vertexValueInitializer: (k: VertexKey) => k as K
238
+ });
239
+ for (const k of keys) g.addVertex(k);
240
+ return g;
241
+ }
242
+
243
+ /**
244
+ * Construct an undirected graph from `[key, value]` entries.
245
+ * @template V - Vertex value type.
246
+ * @param entries - Iterable of `[key, value]` pairs.
247
+ * @returns UndirectedGraph with all vertices added.
248
+ * @remarks Time O(V), Space O(V)
249
+ */
250
+ static fromEntries<V>(
251
+ entries: Iterable<[VertexKey, V]>
252
+ ): UndirectedGraph<V, any, UndirectedVertex<V>, UndirectedEdge<any>> {
253
+ const g: UndirectedGraph<V, any, UndirectedVertex<V>, UndirectedEdge<any>> = new UndirectedGraph<V, any>();
254
+ for (const [k, v] of entries) g.addVertex(k, v);
255
+ return g;
256
+ }
257
+
258
+ /**
259
+ * Create an undirected vertex instance. Does not insert into the graph.
260
+ * @param key - Vertex identifier.
261
+ * @param value - Optional payload.
262
+ * @returns Concrete vertex instance.
263
+ * @remarks Time O(1), Space O(1)
264
+ */
265
+ createVertex(key: VertexKey, value?: VO['value']): VO {
266
+ return new UndirectedVertex(key, value) as VO;
267
+ }
268
+
269
+ /**
270
+ * Create an undirected edge instance. Does not insert into the graph.
271
+ * @param v1 - One endpoint key.
272
+ * @param v2 - The other endpoint key.
273
+ * @param weight - Edge weight; defaults to `defaultEdgeWeight`.
274
+ * @param value - Edge payload.
275
+ * @returns Concrete edge instance.
276
+ * @remarks Time O(1), Space O(1)
277
+ */
278
+ override createEdge(v1: VertexKey, v2: VertexKey, weight?: number, value?: EO['value']): EO {
279
+ return new UndirectedEdge(v1, v2, weight ?? this.options.defaultEdgeWeight ?? 1, value) as EO;
280
+ }
281
+
282
+ /**
283
+ * Get an undirected edge between two vertices, if present.
284
+ * @param v1 - One vertex or key.
285
+ * @param v2 - The other vertex or key.
286
+ * @returns Edge instance or `undefined`.
287
+ * @remarks Time O(1) avg, Space O(1)
288
+ */
289
+ getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
290
+ let edgeMap: EO[] | undefined = [];
291
+
292
+ if (v1 !== undefined && v2 !== undefined) {
293
+ const vertex1: VO | undefined = this._getVertex(v1);
294
+ const vertex2: VO | undefined = this._getVertex(v2);
295
+
296
+ if (vertex1 && vertex2) {
297
+ edgeMap = this._edgeMap.get(vertex1)?.filter(e => e.endpoints.includes(vertex2.key));
298
+ }
299
+ }
300
+
301
+ return edgeMap ? edgeMap[0] || undefined : undefined;
302
+ }
303
+
304
+ /**
305
+ * Delete a single undirected edge between two vertices.
306
+ * @param v1 - One vertex or key.
307
+ * @param v2 - The other vertex or key.
308
+ * @returns Removed edge or `undefined`.
309
+ * @remarks Time O(1) avg, Space O(1)
310
+ */
311
+ deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {
312
+ const vertex1: VO | undefined = this._getVertex(v1);
313
+ const vertex2: VO | undefined = this._getVertex(v2);
314
+
315
+ if (!vertex1 || !vertex2) {
316
+ return undefined;
317
+ }
318
+
319
+ const v1Edges = this._edgeMap.get(vertex1);
320
+ let removed: EO | undefined = undefined;
321
+ if (v1Edges) {
322
+ removed = arrayRemove<EO>(v1Edges, (e: EO) => e.endpoints.includes(vertex2.key))[0] || undefined;
323
+ }
324
+ const v2Edges = this._edgeMap.get(vertex2);
325
+ if (v2Edges) {
326
+ arrayRemove<EO>(v2Edges, (e: EO) => e.endpoints.includes(vertex1.key));
327
+ }
328
+ return removed;
329
+ }
330
+
331
+ /**
332
+ * Delete an edge by instance or by a pair of keys.
333
+ * @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
334
+ * @param otherSideVertexKey - Required second endpoint when deleting by pair.
335
+ * @returns Removed edge or `undefined`.
336
+ * @remarks Time O(1) avg, Space O(1)
337
+ */
338
+ deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {
339
+ let oneSide: VO | undefined, otherSide: VO | undefined;
340
+ if (this.isVertexKey(edgeOrOneSideVertexKey)) {
341
+ if (this.isVertexKey(otherSideVertexKey)) {
342
+ oneSide = this._getVertex(edgeOrOneSideVertexKey);
343
+ otherSide = this._getVertex(otherSideVertexKey);
344
+ } else {
345
+ return;
346
+ }
347
+ } else {
348
+ oneSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[0]);
349
+ otherSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[1]);
350
+ }
351
+
352
+ if (oneSide && otherSide) {
353
+ return this.deleteEdgeBetween(oneSide, otherSide);
354
+ } else {
355
+ return;
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Delete a vertex and remove it from all neighbor lists.
361
+ * @param vertexOrKey - Vertex or key.
362
+ * @returns `true` if removed; otherwise `false`.
363
+ * @remarks Time O(deg), Space O(1)
364
+ */
365
+ deleteVertex(vertexOrKey: VO | VertexKey): boolean {
366
+ let vertexKey: VertexKey;
367
+ let vertex: VO | undefined;
368
+ if (this.isVertexKey(vertexOrKey)) {
369
+ vertex = this.getVertex(vertexOrKey);
370
+ vertexKey = vertexOrKey;
371
+ } else {
372
+ vertex = vertexOrKey;
373
+ vertexKey = this._getVertexKey(vertexOrKey);
374
+ }
375
+
376
+ /**
377
+ * All neighbors connected via undirected edges.
378
+ * @param vertexOrKey - Vertex or key.
379
+ * @returns Array of neighbor vertices.
380
+ * @remarks Time O(deg), Space O(deg)
381
+ */
382
+ const neighbors = this.getNeighbors(vertexOrKey);
383
+
384
+ if (vertex) {
385
+ neighbors.forEach(neighbor => {
386
+ const neighborEdges = this._edgeMap.get(neighbor);
387
+ if (neighborEdges) {
388
+ const restEdges = neighborEdges.filter(edge => {
389
+ return !edge.endpoints.includes(vertexKey);
390
+ });
391
+ this._edgeMap.set(neighbor, restEdges);
392
+ }
393
+ });
394
+ this._edgeMap.delete(vertex);
395
+ }
396
+
397
+ return this._vertexMap.delete(vertexKey);
398
+ }
399
+
400
+ /**
401
+ * Degree of a vertex (# of incident undirected edges).
402
+ * @param vertexOrKey - Vertex or key.
403
+ * @returns Non-negative integer.
404
+ * @remarks Time O(1) avg, Space O(1)
405
+ */
406
+ degreeOf(vertexOrKey: VertexKey | VO): number {
407
+ const vertex = this._getVertex(vertexOrKey);
408
+ if (vertex) {
409
+ return this._edgeMap.get(vertex)?.length || 0;
410
+ } else {
411
+ return 0;
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Incident undirected edges of a vertex.
417
+ * @param vertexOrKey - Vertex or key.
418
+ * @returns Array of incident edges.
419
+ * @remarks Time O(deg), Space O(deg)
420
+ */
421
+ edgesOf(vertexOrKey: VertexKey | VO): EO[] {
422
+ const vertex = this._getVertex(vertexOrKey);
423
+ if (vertex) {
424
+ return this._edgeMap.get(vertex) || [];
425
+ } else {
426
+ return [];
427
+ }
428
+ }
429
+
430
+ /**
431
+ * Unique set of undirected edges across endpoints.
432
+ * @returns Array of edges.
433
+ * @remarks Time O(E), Space O(E)
434
+ */
435
+ edgeSet(): EO[] {
436
+ const edgeSet: Set<EO> = new Set();
437
+ this._edgeMap.forEach(edgeMap => {
438
+ edgeMap.forEach(edge => {
439
+ edgeSet.add(edge);
440
+ });
441
+ });
442
+ return [...edgeSet];
443
+ }
444
+
445
+ getNeighbors(vertexOrKey: VO | VertexKey): VO[] {
446
+ const neighbors: VO[] = [];
447
+ const vertex = this._getVertex(vertexOrKey);
448
+ if (vertex) {
449
+ const neighborEdges = this.edgesOf(vertex);
450
+ for (const edge of neighborEdges) {
451
+ const neighbor = this._getVertex(edge.endpoints.filter(e => e !== vertex.key)[0]);
452
+ if (neighbor) {
453
+ neighbors.push(neighbor);
454
+ }
455
+ }
456
+ }
457
+ return neighbors;
458
+ }
459
+
460
+ /**
461
+ * Resolve an edge's two endpoints to vertex instances.
462
+ * @param edge - Edge instance.
463
+ * @returns `[v1, v2]` or `undefined` if either endpoint is missing.
464
+ * @remarks Time O(1), Space O(1)
465
+ */
466
+ getEndsOfEdge(edge: EO): [VO, VO] | undefined {
467
+ if (!this.hasEdge(edge.endpoints[0], edge.endpoints[1])) {
468
+ return undefined;
469
+ }
470
+ const v1 = this._getVertex(edge.endpoints[0]);
471
+ const v2 = this._getVertex(edge.endpoints[1]);
472
+ if (v1 && v2) {
473
+ return [v1, v2];
474
+ } else {
475
+ return undefined;
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Whether the graph has no vertices and no edges.
481
+ * @remarks Time O(1), Space O(1)
482
+ */
483
+ isEmpty(): boolean {
484
+ return this.vertexMap.size === 0 && this.edgeMap.size === 0;
485
+ }
486
+
487
+ /**
488
+ * Remove all vertices and edges.
489
+ * @remarks Time O(V + E), Space O(1)
490
+ */
491
+ clear() {
492
+ this._vertexMap = new Map<VertexKey, VO>();
493
+ this._edgeMap = new Map<VO, EO[]>();
494
+ }
495
+
496
+ /**
497
+ * Deep clone as the same concrete class.
498
+ * @returns A new graph of the same concrete class (`this` type).
499
+ * @remarks Time O(V + E), Space O(V + E)
500
+ */
501
+ override clone(): this {
502
+ return super.clone();
503
+ }
504
+
505
+ /**
506
+ * Tarjan-based bridge and articulation point detection.
507
+ * @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
508
+ * @remarks Time O(V + E), Space O(V + E)
509
+ */
510
+ tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {
511
+ const dfnMap = new Map<VO, number>();
512
+ const lowMap = new Map<VO, number>();
513
+ const bridges: EO[] = [];
514
+ const cutVertices: VO[] = [];
515
+
516
+ let time = 0;
517
+
518
+ const dfs = (vertex: VO, parent: VO | undefined) => {
519
+ dfnMap.set(vertex, time);
520
+ lowMap.set(vertex, time);
521
+ time++;
522
+
523
+ const neighbors = this.getNeighbors(vertex);
524
+ let childCount = 0;
525
+
526
+ for (const neighbor of neighbors) {
527
+ if (!dfnMap.has(neighbor)) {
528
+ childCount++;
529
+ dfs(neighbor, vertex);
530
+ lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));
531
+
532
+ if (lowMap.get(neighbor)! > dfnMap.get(vertex)!) {
533
+ // Found a bridge
534
+ const edge = this.getEdge(vertex, neighbor);
535
+ if (edge) {
536
+ bridges.push(edge);
537
+ }
538
+ }
539
+
540
+ if (parent !== undefined && lowMap.get(neighbor)! >= dfnMap.get(vertex)!) {
541
+ // Found an articulation point
542
+ cutVertices.push(vertex);
543
+ }
544
+ } else if (neighbor !== parent) {
545
+ lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));
546
+ }
547
+ }
548
+
549
+ if (parent === undefined && childCount > 1) {
550
+ // Special case for root in DFS tree
551
+ cutVertices.push(vertex);
552
+ }
553
+ };
554
+
555
+ for (const vertex of this.vertexMap.values()) {
556
+ if (!dfnMap.has(vertex)) {
557
+ dfs(vertex, undefined);
558
+ }
559
+ }
560
+
561
+ return {
562
+ dfnMap,
563
+ lowMap,
564
+ bridges,
565
+ cutVertices
566
+ };
567
+ }
568
+
569
+ /**
570
+ * Get bridges discovered by `tarjan()`.
571
+ * @returns Array of edges that are bridges.
572
+ * @remarks Time O(B), Space O(1)
573
+ */
574
+ getBridges() {
575
+ return this.tarjan().bridges;
576
+ }
577
+
578
+ /**
579
+ * Get articulation points discovered by `tarjan()`.
580
+ * @returns Array of cut vertices.
581
+ * @remarks Time O(C), Space O(1)
582
+ */
583
+ getCutVertices() {
584
+ return this.tarjan().cutVertices;
585
+ }
586
+
587
+ /**
588
+ * DFN index map computed by `tarjan()`.
589
+ * @returns Map from vertex to DFN index.
590
+ * @remarks Time O(V), Space O(V)
591
+ */
592
+ getDFNMap() {
593
+ return this.tarjan().dfnMap;
594
+ }
595
+
596
+ /**
597
+ * LOW link map computed by `tarjan()`.
598
+ * @returns Map from vertex to LOW value.
599
+ * @remarks Time O(V), Space O(V)
600
+ */
601
+ getLowMap() {
602
+ return this.tarjan().lowMap;
603
+ }
604
+
605
+ /**
606
+ * Internal hook to attach an undirected edge into adjacency maps.
607
+ * @param edge - Edge instance.
608
+ * @returns `true` if both endpoints exist; otherwise `false`.
609
+ * @remarks Time O(1) avg, Space O(1)
610
+ */
611
+ protected _addEdge(edge: EO): boolean {
612
+ for (const end of edge.endpoints) {
613
+ const endVertex = this._getVertex(end);
614
+ if (endVertex === undefined) return false;
615
+ if (endVertex) {
616
+ const edgeMap = this._edgeMap.get(endVertex);
617
+ if (edgeMap) {
618
+ edgeMap.push(edge);
619
+ } else {
620
+ this._edgeMap.set(endVertex, [edge]);
621
+ }
622
+ }
623
+ }
624
+ return true;
625
+ }
626
+ }