@@ -26,7 +26,7 @@ class AdjacencyListGraph<T>(
26
26
if (vertex == it.source) it.destination else it.source
27
27
}?.toSet() ? : setOf ()
28
28
29
- override fun root () = vertices.keys.first ()
29
+ override fun root () = vertices.keys.firstOrNull ()
30
30
31
31
override fun size () = vertices.keys.size
32
32
@@ -48,4 +48,228 @@ class AdjacencyListGraph<T>(
48
48
)
49
49
50
50
override fun vertex (id : Long ) = vertices.keys.find { it.id == id }
51
+
52
+ /* *
53
+ * Builder for adjacency list graphs.
54
+ */
55
+ class Builder <T > {
56
+ /* *
57
+ * Builder for an edge in an adjacency list graph.
58
+ * @param source Source [Vertex].
59
+ * @param destination Destination vertex.
60
+ */
61
+ class EdgeBuilder <T >(
62
+ private val source : Vertex <T >,
63
+ private val destination : Vertex <T >,
64
+ ) {
65
+ private var isDirected: Boolean = false
66
+ private var weight: Long = 0L
67
+
68
+ /* *
69
+ * Instantiates a new [Edge] from this builder.
70
+ * @return Edge.
71
+ */
72
+ fun build () = Edge (source, destination, isDirected, weight)
73
+
74
+ /* *
75
+ * Marks this builder's edge as directed.
76
+ */
77
+ fun directed () {
78
+ isDirected = true
79
+ }
80
+
81
+ /* *
82
+ * Sets the weight of this builder's edge.
83
+ * @param value Weight.
84
+ */
85
+ fun weight (value : Long ) {
86
+ weight = value
87
+ }
88
+ }
89
+
90
+ private val edges = mutableSetOf<Edge <T >>()
91
+ private val vertices = mutableMapOf<Vertex <T >, MutableSet <Edge <T >>>()
92
+
93
+ /* *
94
+ * Instantiates a new [AdjacencyListGraph] from this builder.
95
+ * @return Adjacency list graph.
96
+ */
97
+ fun build () = AdjacencyListGraph (vertices, edges)
98
+
99
+ /* *
100
+ * Type-safe builder for creating an [Edge] of a graph from an existing
101
+ * pair of [Vertex].
102
+ *
103
+ * Example usage:
104
+ * ```
105
+ * vertex("a")
106
+ * vertex("b")
107
+ *
108
+ * edge(0, 1) { // First vertex has ID of 0, second vertex has ID of 1
109
+ * directed()
110
+ * weight(10L)
111
+ * }
112
+ * ```
113
+ * @param sourceId Source vertex ID.
114
+ * @param destinationId Destination vertex ID.
115
+ * @param init Function with receiver.
116
+ * @return Edge.
117
+ */
118
+ fun edge (
119
+ sourceId : Long ,
120
+ destinationId : Long ,
121
+ init : (EdgeBuilder <T >.() -> Unit )? = null,
122
+ ) = edge(
123
+ vertices.keys.find { it.id == sourceId }!! ,
124
+ vertices.keys.find { it.id == destinationId }!! ,
125
+ init ,
126
+ )
127
+
128
+ /* *
129
+ * Type-safe builder for creating an [Edge] of a graph from an existing
130
+ * pair of [Vertex].
131
+ *
132
+ * Note that the first vertex matching each value will be used,
133
+ * avoid this method when building a graph whose nodes have duplicate values.
134
+ *
135
+ * Example usage:
136
+ * ```
137
+ * vertex("a")
138
+ * vertex("b")
139
+ *
140
+ * edge("a", "b") {
141
+ * directed()
142
+ * weight(10L)
143
+ * }
144
+ * ```
145
+ * @param source Source vertex value.
146
+ * @param destination Destination vertex value.
147
+ * @param init Function with receiver.
148
+ * @return Edge.
149
+ */
150
+ fun edge (
151
+ source : T ,
152
+ destination : T ,
153
+ init : (EdgeBuilder <T >.() -> Unit )? = null,
154
+ ) = edge(
155
+ vertices.keys.find { it.value == source }!! ,
156
+ vertices.keys.find { it.value == destination }!! ,
157
+ init ,
158
+ )
159
+
160
+ /* *
161
+ * Type-safe builder for creating an [Edge] of a graph from a pair of existing [Vertex].
162
+ * Used internally by more fluent builders (e.g. by-ID or by-value edge builders).
163
+ * @param source Source vertex.
164
+ * @param destination Destination vertex.
165
+ * @param init Function with receiver.
166
+ * @return Edge.
167
+ */
168
+ private fun edge (
169
+ source : Vertex <T >,
170
+ destination : Vertex <T >,
171
+ init : (EdgeBuilder <T >.() -> Unit )? = null,
172
+ ): Edge <T > {
173
+ val builder = EdgeBuilder (source, destination)
174
+ init ?.invoke(builder)
175
+
176
+ val edge = builder.build()
177
+ vertices[source]?.add(edge)
178
+ vertices[destination]?.add(edge)
179
+ edges.add(edge)
180
+
181
+ return edge
182
+ }
183
+
184
+ /* *
185
+ * Type-safe builder for creating a [Vertex] of a graph.
186
+ *
187
+ * Example usage:
188
+ * ```
189
+ * vertex("a")
190
+ * ```
191
+ * @param value Value.
192
+ * @param init Function with receiver.
193
+ * @return Vertex.
194
+ */
195
+ fun vertex (
196
+ value : T ,
197
+ init : (Vertex <T >.() -> Unit )? = null,
198
+ ) = vertex(
199
+ vertices.size.toLong(),
200
+ value,
201
+ init ,
202
+ )
203
+
204
+ /* *
205
+ * Type-safe builder for creating a [Vertex] of a graph from an existing vertex. ID and value
206
+ * of the given vertex will be copied.
207
+ *
208
+ * Example usage:
209
+ * ```
210
+ * val other = someOtherVertex()
211
+ * vertex(other)
212
+ * ```
213
+ * @param vertex Vertex to copy.
214
+ * @param init Function with receiver.
215
+ * @return Vertex.
216
+ */
217
+ fun vertex (
218
+ vertex : Vertex <T >,
219
+ init : (Vertex <T >.() -> Unit )? = null,
220
+ ) = vertex(
221
+ vertex.id,
222
+ vertex.value,
223
+ init ,
224
+ )
225
+
226
+ /* *
227
+ * Type-safe builder for creating a [Vertex] of a graph.
228
+ *
229
+ * Example usage:
230
+ * ```
231
+ * vertex(0, "a")
232
+ * ```
233
+ * @param id ID.
234
+ * @param value Value.
235
+ * @param init Function with receiver.
236
+ * @return Vertex.
237
+ */
238
+ private fun vertex (
239
+ id : Long ,
240
+ value : T ,
241
+ init : (Vertex <T >.() -> Unit )? = null,
242
+ ): Vertex <T > {
243
+ val vertex = Vertex (id, value)
244
+ init ?.invoke(vertex)
245
+ vertices[vertex] = mutableSetOf ()
246
+ return vertex
247
+ }
248
+ }
249
+ }
250
+
251
+ /* *
252
+ * Type-safe builder for creating an [AdjacencyListGraph].
253
+ *
254
+ * Example usage:
255
+ * ```
256
+ * graph {
257
+ * vertex("a")
258
+ * vertex("b")
259
+ * vertex("c")
260
+ *
261
+ * edge(1, 2)
262
+ * edge(2, 3) {
263
+ * directed()
264
+ * weight(10L)
265
+ * }
266
+ * }
267
+ * ```
268
+ * @param init Function with receiver.
269
+ * @return Adjacency list graph.
270
+ */
271
+ fun <T > graph (init : AdjacencyListGraph .Builder <T >.() -> Unit ): AdjacencyListGraph <T > {
272
+ val builder = AdjacencyListGraph .Builder <T >()
273
+ builder.init ()
274
+ return builder.build()
51
275
}
0 commit comments