-
Notifications
You must be signed in to change notification settings - Fork 5
/
Graph+Components.swift
55 lines (41 loc) · 1.8 KB
/
Graph+Components.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import SwiftyToolz
public extension Graph
{
/**
Find the [components](https://en.wikipedia.org/wiki/Component_(graph_theory)) of the `Graph`
- Returns: Multiple sets of nodes which represent the components of the graph
*/
func findComponents() -> Set<NodeIDs>
{
var visitedNodes = NodeIDs()
var components = Set<NodeIDs>()
for node in nodeIDs
{
if visitedNodes.contains(node) { continue }
// this node has not been visited yet
components += Set(findLackingNodes(forComponent: [],
startingAt: node,
visitedNodes: &visitedNodes))
visitedNodes.insert(node)
}
return components
}
/// startNode is connected to the incompleteComponent but not contained in it. both will be in the resulting actual component.
private func findLackingNodes(forComponent incompleteComponent: [NodeID],
startingAt startNode: NodeID,
visitedNodes: inout NodeIDs) -> [NodeID]
{
var lackingNodes = [startNode]
visitedNodes += startNode
let neighbours = node(with: startNode)?.neighbourIDs ?? []
for neighbour in neighbours
{
if visitedNodes.contains(neighbour) { continue }
let extendedComponent = incompleteComponent + lackingNodes
lackingNodes += findLackingNodes(forComponent: extendedComponent,
startingAt: neighbour,
visitedNodes: &visitedNodes)
}
return lackingNodes
}
}