Completed
Branch develop (c353cc)
by Greg
02:27
created

ConnectedComponent   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 9
c 1
b 0
f 0
lcom 1
cbo 0
dl 0
loc 75
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A findConnectedComponents() 0 15 2
A groupResults() 0 12 3
A depthFirstSearch() 0 9 3
1
<?php
2
namespace Fisharebest\Algorithm;
3
4
/**
5
 * @package   fisharebest/algorithm
6
 * @author    Greg Roach <[email protected]>
7
 * @copyright (c) 2015 Greg Roach <[email protected]>
8
 * @license   GPL-3.0+
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
/**
23
 * Class ConnectedComponent - Use a depth-first search to find connected
24
 * components of an undirected graph.
25
 */
26
class ConnectedComponent {
27
	/** @var integer[][] The graph, where $graph[node1][node2]=cost */
28
	protected $graph;
29
30
	/** @var integer[] The component number for each node */
31
	protected $nodes;
32
33
	/** @var int The next connected-component to find. */
34
	protected $component;
35
36
	/**
37
	 * @param integer[][] $graph
38
	 */
39
	public function __construct($graph) {
40
		$this->graph     = $graph;
41
		$this->nodes     = array_fill_keys(array_keys($graph), 0);
42
		$this->component = 0;
43
	}
44
45
	/**
46
	 * An array of components (arrays).
47
	 *
48
	 * @return array
49
	 */
50
	public function findConnectedComponents() {
51
		// Find the first unallocated node
52
		$node = array_search(0, $this->nodes, true);
53
54
		while ($node !== false) {
55
			// Find the next connected-component.
56
			$this->component++;
57
			$this->depthFirstSearch($node, $this->component);
58
59
			// Find the next unallocated node.
60
			$node = array_search(0, $this->nodes, true);
61
		}
62
63
		return $this->groupResults();
64
	}
65
66
	/**
67
	 * Group the nodes by component
68
	 *
69
	 * @return array
70
	 */
71
	private function groupResults() {
72
		$result = array();
73
		foreach ($this->nodes as $node => $component) {
74
			if (array_key_exists($component, $result)) {
75
				$result[$component][] = $node;
76
			} else {
77
				$result[$component] = array($node);
78
			}
79
		}
80
81
		return $result;
82
	}
83
84
	/**
85
	 * Find all nodes connected to $node and mark them as part of
86
	 * component $component.
87
	 *
88
	 * @param $node
89
	 * @param $component
90
	 */
91
	private function depthFirstSearch($node, $component) {
92
		$this->nodes[$node] = $component;
93
94
		foreach (array_keys($this->graph[$node]) as $next) {
95
			if ($this->nodes[$next] === 0) {
96
				$this->depthFirstSearch($next, $component);
97
			}
98
		}
99
	}
100
}
101