Skip to content

Commit

Permalink
Implemented AVL Tree Data Structure. Added serialization/deserializat…
Browse files Browse the repository at this point in the history
…ion feature. Added corresponding unit test.
  • Loading branch information
Ramy-Badr-Ahmed committed Oct 12, 2024
1 parent d11e757 commit e145894
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 4 deletions.
82 changes: 80 additions & 2 deletions DataStructures/AVLTree/AVLTree.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php

/*
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request: #163
* https://github.com/TheAlgorithms/PHP/pull/163
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
* in Pull Request #163: https://github.com/TheAlgorithms/PHP/pull/163
* and #173: https://github.com/TheAlgorithms/PHP/pull/173
*
* Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request addressing bugs/corrections to this file.
* Thank you!
Expand Down Expand Up @@ -311,4 +312,81 @@ private function getMinNode(AVLTreeNode $node): AVLTreeNode
}
return $node;
}

/**
* Serializes the segment tree into a JSON string.
*
* @return string The serialized AVL Tree as a JSON string.
*/
public function serialize(): string
{
return json_encode($this->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);
}
}
}
67 changes: 65 additions & 2 deletions tests/DataStructures/AVLTreeTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php

/*
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed) in Pull Request: #163
* https://github.com/TheAlgorithms/PHP/pull/163
* Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
* in Pull Request #163: https://github.com/TheAlgorithms/PHP/pull/163
* and #173: https://github.com/TheAlgorithms/PHP/pull/173
*
* Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request addressing bugs/corrections to this file.
* Thank you!
Expand Down Expand Up @@ -37,6 +38,9 @@ private function populateTree(): void
$this->tree->insert(15, 'Value 15');
}

/**
* Tests the insert and search operations in the AVLTree.
*/
public function testInsertAndSearch(): void
{
$this->populateTree();
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand All @@ -186,6 +197,9 @@ public function testLargeTree(): void
}
}

/**
* Tests whether the AVLTree remains balanced after insertions.
*/
public function testBalance(): void
{
$this->populateTree();
Expand Down Expand Up @@ -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'
);
}
}

0 comments on commit e145894

Please sign in to comment.