-
-
Notifications
You must be signed in to change notification settings - Fork 469
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented Disjoint Set (Union-Find) Data Structure (#160)
* Added Disjoint Sets Data structure * Moved DisjointSetTest.php to tests/DataStructures * Update DataStructures/DisjointSets/DisjointSet.php Co-authored-by: Brandon Johnson <[email protected]> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <[email protected]> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <[email protected]> * Considered PHPCS remarks. Unit Testing is now working. * Remove data type mixed. Considered annotations for php7.4. * Remove data type mixed. Considered annotations for php7.4. * updating DIRECTORY.md --------- Co-authored-by: Brandon Johnson <[email protected]> Co-authored-by: Ramy-Badr-Ahmed <[email protected]>
- Loading branch information
1 parent
9a80c3a
commit 193d032
Showing
5 changed files
with
155 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
namespace DataStructures\DisjointSets; | ||
|
||
class DisjointSet | ||
{ | ||
/** | ||
* Finds the representative of the set that contains the node. | ||
*/ | ||
public function findSet(DisjointSetNode $node): DisjointSetNode | ||
{ | ||
if ($node !== $node->parent) { | ||
// Path compression: make the parent point directly to the root | ||
$node->parent = $this->findSet($node->parent); | ||
} | ||
return $node->parent; | ||
} | ||
|
||
/** | ||
* Unites the sets that contain x and y. | ||
*/ | ||
public function unionSet(DisjointSetNode $nodeX, DisjointSetNode $nodeY): void | ||
{ | ||
$rootX = $this->findSet($nodeX); | ||
$rootY = $this->findSet($nodeY); | ||
|
||
if ($rootX === $rootY) { | ||
return; // They are already in the same set | ||
} | ||
|
||
// Union by rank: attach the smaller tree under the larger tree | ||
if ($rootX->rank > $rootY->rank) { | ||
$rootY->parent = $rootX; | ||
} else { | ||
$rootX->parent = $rootY; | ||
if ($rootX->rank === $rootY->rank) { | ||
$rootY->rank += 1; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace DataStructures\DisjointSets; | ||
|
||
class DisjointSetNode | ||
{ | ||
/** | ||
* @var int|string|float|null | ||
*/ | ||
// PHP7.4: Defined with annotations | ||
public $data; # replace with type hint "mixed" as of PHP 8.0^. | ||
public int $rank; | ||
public DisjointSetNode $parent; | ||
|
||
public function __construct($data = null) | ||
{ | ||
$this->data = $data; | ||
$this->rank = 0; | ||
$this->parent = $this; // Initialize parent to itself | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<?php | ||
|
||
namespace DataStructures; | ||
|
||
require_once __DIR__ . '/../../DataStructures/DisjointSets/DisjointSet.php'; | ||
require_once __DIR__ . '/../../DataStructures/DisjointSets/DisjointSetNode.php'; | ||
|
||
use DataStructures\DisjointSets\DisjointSet; | ||
use DataStructures\DisjointSets\DisjointSetNode; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class DisjointSetTest extends TestCase | ||
{ | ||
private DisjointSet $ds; | ||
private array $nodes; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->ds = new DisjointSet(); | ||
$this->nodes = []; | ||
|
||
// Create 20 nodes | ||
for ($i = 0; $i < 20; $i++) { | ||
$this->nodes[$i] = new DisjointSetNode($i); | ||
} | ||
|
||
// Perform union operations to form several disjoint sets | ||
$this->ds->unionSet($this->nodes[0], $this->nodes[1]); | ||
$this->ds->unionSet($this->nodes[1], $this->nodes[2]); | ||
|
||
$this->ds->unionSet($this->nodes[3], $this->nodes[4]); | ||
$this->ds->unionSet($this->nodes[4], $this->nodes[5]); | ||
|
||
$this->ds->unionSet($this->nodes[6], $this->nodes[7]); | ||
$this->ds->unionSet($this->nodes[7], $this->nodes[8]); | ||
|
||
$this->ds->unionSet($this->nodes[9], $this->nodes[10]); | ||
$this->ds->unionSet($this->nodes[10], $this->nodes[11]); | ||
|
||
$this->ds->unionSet($this->nodes[12], $this->nodes[13]); | ||
$this->ds->unionSet($this->nodes[13], $this->nodes[14]); | ||
|
||
$this->ds->unionSet($this->nodes[15], $this->nodes[16]); | ||
$this->ds->unionSet($this->nodes[16], $this->nodes[17]); | ||
|
||
$this->ds->unionSet($this->nodes[18], $this->nodes[19]); | ||
} | ||
|
||
public function testFindSet(): void | ||
{ | ||
// Nodes in the same sets should have the same root | ||
for ($i = 0; $i < 6; $i++) { | ||
for ($j = 0; $j < 6; $j++) { | ||
$setI = $this->ds->findSet($this->nodes[$i]); | ||
$setJ = $this->ds->findSet($this->nodes[$j]); | ||
|
||
if ($this->inSameSet($i, $j)) { | ||
$this->assertSame($setI, $setJ, "Nodes $i and $j should be in the same set"); | ||
} else { | ||
$this->assertNotSame($setI, $setJ, "Nodes $i and $j should be in different sets"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private function inSameSet(int $i, int $j): bool | ||
{ | ||
// Define which nodes should be in the same set based on union operations | ||
$sets = [ | ||
[0, 1, 2], // Set A | ||
[3, 4, 5], // Set B | ||
[6, 7, 8], // Set C | ||
[9, 10, 11], // Set D | ||
[12, 13, 14], // Set E | ||
[15, 16, 17], // Set F | ||
[18, 19] // Set G | ||
]; | ||
|
||
foreach ($sets as $set) { | ||
if (in_array($i, $set) && in_array($j, $set)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} |