Skip to content

Commit

Permalink
Issue #11: Improve the NaryNode.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Jun 15, 2019
1 parent 1ce4437 commit c3de5fc
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 21 deletions.
13 changes: 8 additions & 5 deletions spec/drupol/phptree/Node/NaryNodeSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ public function it_can_have_children()
$child2 = new NaryNode(2);
$child3 = new Node();
$child4 = new Node();
$child5 = new Node();
$child6 = new Node();
$child7 = new Node();

$this
->add($child1, $child2, $child3, $child4, $child5, $child6, $child7);
->add($child1, $child2, $child3, $child4);

$this->degree()->shouldReturn(2);
$this->count()->shouldReturn(4);

$this->shouldThrow(\Exception::class)
->during('add', [new Node()]);
}

public function it_can_throw_an_error_when_capacity_is_invalid()
Expand All @@ -72,7 +72,10 @@ public function it_can_throw_an_error_when_capacity_is_invalid()

$this
->capacity()
->shouldReturn(0);
->shouldReturn(-5);

$this->shouldThrow(\Exception::class)
->during('add', [new NaryNode()]);
}

public function it_can_use_a_different_traverser()
Expand Down
55 changes: 39 additions & 16 deletions src/Node/NaryNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ public function __construct(int $capacity = 0, NodeInterface $parent = null, Tra
{
parent::__construct($parent);

$capacity = 0 > $capacity ?
0 :
$capacity;

$this->storage()->set(
'capacity',
$capacity
Expand All @@ -56,18 +52,10 @@ public function add(NodeInterface ...$nodes): NodeInterface
continue;
}

foreach ($this->getTraverser()->traverse($this) as $candidate) {
if (!($candidate instanceof NaryNodeInterface)) {
continue;
}

if ($candidate->degree() >= $candidate->capacity()) {
continue;
}

$candidate->add($node);

break;
if (null !== $parent = $this->findFirstAvailableNode($this)) {
$parent->add($node);
} else {
throw new \Exception('Unable to add the node to the tree.');
}
}

Expand Down Expand Up @@ -105,4 +93,39 @@ public function offsetSet($offset, $value)
parent::offsetSet($offset, $value);
}
}

/**
* Find the first available node in the tree.
*
* When adding nodes to a NaryNode based tree, you must traverse the tree
* and find the first node that can be used as a parent for the node to add.
*
* @param \drupol\phptree\Node\NodeInterface $tree
* The base node.
*
* @return null|\drupol\phptree\Node\NodeInterface
* A node, null if none are found.
*/
protected function findFirstAvailableNode(NodeInterface $tree): ?NodeInterface
{
foreach ($this->getTraverser()->traverse($tree) as $candidate) {
if (!($candidate instanceof NaryNodeInterface)) {
continue;
}

$capacity = $candidate->capacity();

if (0 > $capacity) {
continue;
}

if (0 !== $capacity && $candidate->degree() >= $capacity) {
continue;
}

return $candidate;
}

return null;
}
}

0 comments on commit c3de5fc

Please sign in to comment.