diff --git a/DIRECTORY.md b/DIRECTORY.md index 53f6003..9e56745 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -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) diff --git a/DataStructures/DisjointSets/DisjointSet.php b/DataStructures/DisjointSets/DisjointSet.php new file mode 100644 index 0000000..4212ece --- /dev/null +++ b/DataStructures/DisjointSets/DisjointSet.php @@ -0,0 +1,41 @@ +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; + } + } + } +} diff --git a/DataStructures/DisjointSets/DisjointSetNode.php b/DataStructures/DisjointSets/DisjointSetNode.php new file mode 100644 index 0000000..ed9d755 --- /dev/null +++ b/DataStructures/DisjointSets/DisjointSetNode.php @@ -0,0 +1,21 @@ +data = $data; + $this->rank = 0; + $this->parent = $this; // Initialize parent to itself + } +} diff --git a/composer.json b/composer.json index 8cc0cbd..534b982 100644 --- a/composer.json +++ b/composer.json @@ -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" } } + diff --git a/tests/DataStructures/DisjointSetTest.php b/tests/DataStructures/DisjointSetTest.php new file mode 100644 index 0000000..0a52dea --- /dev/null +++ b/tests/DataStructures/DisjointSetTest.php @@ -0,0 +1,87 @@ +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; + } +}