mirror of
https://github.com/TheAlgorithms/PHP.git
synced 2025-07-26 11:20:12 +02:00
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 <bbj1979@gmail.com> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <bbj1979@gmail.com> * Update DataStructures/DisjointSets/DisjointSetNode.php Co-authored-by: Brandon Johnson <bbj1979@gmail.com> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <bbj1979@gmail.com> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <bbj1979@gmail.com> * Update tests/DataStructures/DisjointSetTest.php Co-authored-by: Brandon Johnson <bbj1979@gmail.com> * 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 <bbj1979@gmail.com> Co-authored-by: Ramy-Badr-Ahmed <Ramy-Badr-Ahmed@users.noreply.github.com>
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
* [Speedconversion](./Conversions/SpeedConversion.php)
|
||||
|
||||
## Datastructures
|
||||
* Disjointsets
|
||||
* [Disjointset](./DataStructures/DisjointSets/DisjointSet.php)
|
||||
* [Disjointsetnode](./DataStructures/DisjointSets/DisjointSetNode.php)
|
||||
* [Doublylinkedlist](./DataStructures/DoublyLinkedList.php)
|
||||
* [Node](./DataStructures/Node.php)
|
||||
* [Queue](./DataStructures/Queue.php)
|
||||
@@ -111,6 +114,7 @@
|
||||
* Conversions
|
||||
* [Conversionstest](./tests/Conversions/ConversionsTest.php)
|
||||
* Datastructures
|
||||
* [Disjointsettest](./tests/DataStructures/DisjointSetTest.php)
|
||||
* [Doublylinkedlisttest](./tests/DataStructures/DoublyLinkedListTest.php)
|
||||
* [Queuetest](./tests/DataStructures/QueueTest.php)
|
||||
* [Singlylinkedlisttest](./tests/DataStructures/SinglyLinkedListTest.php)
|
||||
|
41
DataStructures/DisjointSets/DisjointSet.php
Normal file
41
DataStructures/DisjointSets/DisjointSet.php
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
DataStructures/DisjointSets/DisjointSetNode.php
Normal file
21
DataStructures/DisjointSets/DisjointSetNode.php
Normal file
@@ -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
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name" : "thealgorithms/php",
|
||||
"name": "thealgorithms/php",
|
||||
"description": "All Algorithms implemented in PHP",
|
||||
"config": {
|
||||
"platform": {
|
||||
@@ -19,3 +19,4 @@
|
||||
"test": "vendor/bin/phpunit tests"
|
||||
}
|
||||
}
|
||||
|
||||
|
87
tests/DataStructures/DisjointSetTest.php
Normal file
87
tests/DataStructures/DisjointSetTest.php
Normal file
@@ -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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user