diff --git a/src/helper/Node.php b/src/helper/Node.php index e26255f..f35c64e 100644 --- a/src/helper/Node.php +++ b/src/helper/Node.php @@ -7,9 +7,13 @@ class Node private Node|null $parent; private Node|null $right; private Node|null $left; - private Int $value; + private float|int $value; - public function __construct($value, Node $node = null) + /** + * @param float|int $value + * @param Node|null $node + */ + public function __construct(float|int $value, Node $node = null) { $this->parent = $node; $this->value = $value; @@ -17,52 +21,85 @@ public function __construct($value, Node $node = null) $this->right = null; } + /** + * @return Node|null the parent of the node + */ public function parent(): Node|null { return $this->parent; } - public function value(): Int + /** + * @return float|int + */ + public function value(): float|int { return $this->value; } + /** + * @return Node|null the left child + */ public function left(): Node|null { return $this->left; } + /** + * @return Node|null the right child + */ public function right(): Node|null { return $this->right; } - public function setLeft($value): Node + /** + * set the parent to provided Node + * + * @param ?Node $node + * @return Node + */ + public function setParent(?Node $node): Node { - $newNode = new Node($value, $this); - - return $this->left = $newNode; + return $this->parent = $node; } - public function setRight($value): Node + /** + * set the left child to provided Node + * + * @param ?Node $node + * @return Node + */ + public function setLeft(?Node $node): Node { - $newNode = new Node($value, $this); + return $this->left = $node; + } - return $this->right = $newNode; + /** + * set the right child to provided Node + * + * @param ?Node $node + * @return Node + */ + public function setRight(?Node $node): Node + { + return $this->right = $node; } /** + * travel the tree from the current node and return array representation + * * @return array */ public function flatten(): array { $left = []; $right = []; - if ($this->left() != null) { - $left = $this->left()->flatten(); + if ($this->left != null) { + $left = $this->left->flatten(); } if ($this->right != null) { - $right = $this->right()->flatten(); + $right = $this->right->flatten(); } return array_merge($left, [$this->value], $right); diff --git a/src/helper/Tree.php b/src/helper/Tree.php index 35ea570..e167c44 100644 --- a/src/helper/Tree.php +++ b/src/helper/Tree.php @@ -6,17 +6,28 @@ class Tree { private ?Node $root; - public function __construct($value) + /** + * @param float|int $value + */ + public function __construct(float|int $value) { $this->root = new Node($value); } - public function root(): Node + /** + * @return Node|null + */ + public function root(): ?Node { return $this->root; } - public function put($value, Node $node = null): void + /** + * @param float|int $value + * @param Node|null $node + * @return void + */ + public function put(float|int $value, Node $node = null): void { if ($node == null) { $this->put($value, $this->root); @@ -25,16 +36,78 @@ public function put($value, Node $node = null): void } if ($node->value() < $value) { if ($node->right() == null) { - $node->setRight($value); + $newNode = new Node($value, $node); + $node->setRight($newNode); } else { $this->put($value, $node->right()); } } else { if ($node->left() == null) { - $node->setLeft($value); + $newNode = new Node($value, $node); + $node->setLeft($newNode); } else { $this->put($value, $node->left()); } } } + + /** + * search for node with provided value and remove it from tree + * + * @param float|int $value to search and remove + * @return float|int|null the value found or null on not existing + */ + public function pull(float|int $value): float|int|null + { + $pointer = $this->root; + while ($pointer && $pointer->value() != $value) { + if ($pointer->value() < $value) { + $pointer = $pointer->right(); + } elseif ($value < $pointer->value()) { + $pointer = $pointer->left(); + } + } + if (!$pointer) { + return null; + } + if (!$pointer->parent()) { + $this->root = null; + return $value; + } + if (!$pointer->left() && !$pointer->right()) { + if ($pointer->parent()->left() === $pointer) { + $pointer->parent()->setLeft(null); + } else { + $pointer->parent()->setRight(null); + } + return $value; + } + if(!$pointer->right()) { + $pointer->left()->setParent($pointer->parent()); + if ($pointer->parent()->left() === $pointer) { + $pointer->parent()->setLeft($pointer->left()); + } else { + $pointer->parent()->setRight($pointer->left()); + } + return $value; + } + $inorderSuccessor = $pointer->right(); + while ($inorderSuccessor->left()) { + $inorderSuccessor = $inorderSuccessor->left(); + } + if ($inorderSuccessor->parent()->left() === $inorderSuccessor) { + $inorderSuccessor->parent()->setLeft($inorderSuccessor->right()); + } else { + $inorderSuccessor->parent()->setRight($inorderSuccessor->right()); + } + if ($pointer->parent()->left() === $pointer) { + $pointer->parent()->setLeft($inorderSuccessor); + } else { + $pointer->parent()->setRight($inorderSuccessor); + } + $inorderSuccessor->setRight($pointer->right()); + $inorderSuccessor->setLeft($pointer->left()); + $pointer->left()->setParent($inorderSuccessor); + return $value; + } }