diff --git a/DataStructures/AVLTree/AVLTree.php b/DataStructures/AVLTree/AVLTree.php index ff05ff8..28f0873 100644 --- a/DataStructures/AVLTree/AVLTree.php +++ b/DataStructures/AVLTree/AVLTree.php @@ -1,8 +1,9 @@ serializeTree($this->root)); + } + + /** + * Recursively serializes the AVL Tree. + * + * @param AVLTreeNode|null $node + * @return array + */ + private function serializeTree(?AVLTreeNode $node): array + { + if ($node === null) { + return []; + } + return [ + 'key' => $node->key, + 'value' => $node->value, + 'left' => $this->serializeTree($node->left), + 'right' => $this->serializeTree($node->right), + 'height' => $node->height, + ]; + } + + /** + * Deserializes a JSON string into an AVL Tree object + * + * @param string $data The JSON representation of an AVL Tree to deserialize. + */ + public function deserialize(string $data): void + { + $this->root = $this->deserializeTree(json_decode($data, true)); + $this->counter = 0; + $this->updateNodeCount($this->root); + } + + /** + * Recursively deserializes an AVL Tree from an array representation. + * + * @param array $data The serialized data for the node. + * @return AVLTreeNode|null The root node of the deserialized tree. + */ + private function deserializeTree(array $data): ?AVLTreeNode + { + if (empty($data)) { + return null; + } + + $node = new AVLTreeNode($data['key'], $data['value']); + $node->height = $data['height']; + + $node->left = $this->deserializeTree($data['left']); + $node->right = $this->deserializeTree($data['right']); + + return $node; + } + + /** + * Updates the deserialized tree size. + * + * @param AVLTreeNode|null $node The root node of the deserialized tree. + */ + private function updateNodeCount(?AVLTreeNode $node): void + { + if ($node !== null) { + $this->counter++; + $this->updateNodeCount($node->left); + $this->updateNodeCount($node->right); + } + } } diff --git a/tests/DataStructures/AVLTreeTest.php b/tests/DataStructures/AVLTreeTest.php index 0f1c995..2672911 100644 --- a/tests/DataStructures/AVLTreeTest.php +++ b/tests/DataStructures/AVLTreeTest.php @@ -1,8 +1,9 @@ tree->insert(15, 'Value 15'); } + /** + * Tests the insert and search operations in the AVLTree. + */ public function testInsertAndSearch(): void { $this->populateTree(); @@ -47,6 +51,10 @@ public function testInsertAndSearch(): void $this->assertNull($this->tree->search(25), 'Value for non-existent key 25 should be null'); } + /** + * Tests the deletion of nodes and ensures the AVLTree maintains + * its integrity after deletions. + */ public function testDelete(): void { $this->populateTree(); @@ -167,6 +175,9 @@ public function testInsertDuplicateKeys(): void ); } + /** + * Tests the insertion and deletion of a large number of nodes. + */ public function testLargeTree(): void { // Inserting a large number of nodes @@ -186,6 +197,9 @@ public function testLargeTree(): void } } + /** + * Tests whether the AVLTree remains balanced after insertions. + */ public function testBalance(): void { $this->populateTree(); @@ -300,4 +314,53 @@ public function testSizeOnEmptyTree(): void $this->tree = new AVLTree(); $this->assertEquals(0, $this->tree->size(), 'Size should be 0 for an empty tree'); } + + /** + * Test serialization and deserialization + */ + public function testAVLTreeSerialization(): void + { + $avlTree = new AVLTree(); + + $avlTree->insert(100, 'Value 100'); + $avlTree->insert(200, 'Value 200'); + $avlTree->insert(50, 'Value 50'); + $avlTree->insert(150, 'Value 150'); + $avlTree->insert(350, 'Value 350'); + $avlTree->insert(40, 'Value 40'); + $avlTree->insert(90, 'Value 90'); + + $avlTreeRoot = $avlTree->getRoot(); + $serializedAVLTree = $avlTree->serialize(); + + $deserializedTree = new AVLTree(); + $deserializedTree->deserialize($serializedAVLTree); + + $deserializedTreeRoot = $deserializedTree->getRoot(); + + $this->assertEquals($deserializedTreeRoot->key, $avlTreeRoot->key, 'The two roots key should match'); + $this->assertEquals($deserializedTreeRoot->value, $avlTreeRoot->value, 'The two roots value should match'); + $this->assertEquals( + $deserializedTreeRoot->left->key, + $avlTreeRoot->left->key, + 'Left child of the two roots should match' + ); + $this->assertEquals( + $deserializedTreeRoot->right->key, + $avlTreeRoot->right->key, + 'Left child of the two roots should match' + ); + $this->assertEquals( + $deserializedTreeRoot->height, + $avlTreeRoot->height, + 'The two trees should match in height' + ); + $this->assertEquals($deserializedTree->size(), $avlTree->size(), 'The two trees should match in size'); + + $this->assertSame( + $deserializedTree->inOrderTraversal(), + $avlTree->inOrderTraversal(), + 'Tree structure was not retained' + ); + } }