Skip to content

Commit

Permalink
Merge pull request #3 from drupol/trie-trees
Browse files Browse the repository at this point in the history
Implements a new tree type: Trie
  • Loading branch information
drupol authored Dec 19, 2018
2 parents 78731bb + b3bedaf commit 62b011d
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 14 deletions.
42 changes: 42 additions & 0 deletions spec/drupol/phptree/Node/TrieNodeSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types = 1);

namespace spec\drupol\phptree\Node;

use drupol\phptree\Node\KeyValueNode;
use drupol\phptree\Node\TrieNode;
use PhpSpec\ObjectBehavior;

class TrieNodeSpec extends ObjectBehavior
{
public function it_is_initializable()
{
$this->shouldHaveType(TrieNode::class);
}

public function it_can_add_node()
{
$this->beConstructedWith('root', 'root');

$nodes = [
'ab',
'abc',
'abcd',
'abcde',
'cb',
'cba',
'dcba',
'edcba',
];

foreach ($nodes as $key => $value) {
$nodes[$key] = new KeyValueNode($key, $value);
}

$this
->add(...$nodes)
->count()
->shouldReturn(25);
}
}
8 changes: 1 addition & 7 deletions src/Exporter/Graph.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,7 @@ public function getTraverser(): TraverserInterface
}

/**
* Export a node into a Graph.
*
* @param \drupol\phptree\Node\ValueNodeInterface $node
* The node.
*
* @return \Fhaculty\Graph\Graph
* The graph.
* {@inheritdoc}
*/
public function export(ValueNodeInterface $node): OriginalGraph
{
Expand Down
8 changes: 1 addition & 7 deletions src/Exporter/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@
class Text implements ExporterInterface
{
/**
* Export the node in a string.
*
* @param \drupol\phptree\Node\ValueNodeInterface $node
* The node.
*
* @return string
* The string.
* {@inheritdoc}
*/
public function export(ValueNodeInterface $node): string
{
Expand Down
60 changes: 60 additions & 0 deletions src/Node/TrieNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types = 1);

namespace drupol\phptree\Node;

/**
* Class TrieNode
*/
class TrieNode extends KeyValueNode
{
/**
* {@inheritdoc}
*/
public function add(NodeInterface ...$nodes): NodeInterface
{
foreach ($nodes as $node) {
$data = $node->getValue();

$hash = \hash('sha256', $node->getKey() . $data);

$node = new TrieNode($hash, \substr($data, 0, 1));
$parent = $this->append($node);

$dataWithoutFirstLetter = \substr($data, 1);
if (!empty($dataWithoutFirstLetter)) {
$parent->add(new TrieNode($hash, $dataWithoutFirstLetter));
} else {
$nodes = [$node->getValue()];
foreach ($node->getAncestors() as $ancestor) {
$nodes[] = $ancestor->getValue();
}
\array_pop($nodes);
$node->append(new TrieNode($hash, \strrev(\implode('', $nodes))));
}
}

return $this;
}

/**
* @param \drupol\phptree\Node\ValueNodeInterface $node
*
* @return \drupol\phptree\Node\NodeInterface|\drupol\phptree\Node\ValueNodeInterface
*/
private function append(ValueNodeInterface $node)
{
/** @var \drupol\phptree\Node\ValueNodeInterface $child */
foreach ($this->children() as $child) {
/** @var \drupol\phptree\Node\ValueNodeInterface $node */
if ($node->getValue() === $child->getValue()) {
return $child;
}
}

parent::add($node);

return $node;
}
}
40 changes: 40 additions & 0 deletions tests/src/Exporter/KeyValueGraph.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types = 1);

namespace drupol\phptree\tests\Exporter;

use drupol\phptree\Node\NodeInterface;
use Fhaculty\Graph\Vertex;

/**
* Class KeyValueGraph
*/
class KeyValueGraph extends ValueGraph
{
/**
* {@inheritdoc}
*/
protected function createVertex(NodeInterface $node): Vertex
{
$vertex = parent::createVertex($node);

if (\method_exists($node, 'getValue') && \method_exists($node, 'getKey')) {
$vertex->setAttribute('graphviz.label', $node->getValue());
}

return $vertex;
}

/**
* {@inheritdoc}
*/
protected function createVertexId(NodeInterface $node)
{
if (\method_exists($node, 'getValue') && \method_exists($node, 'getKey')) {
return $node->getKey() . $node->getValue();
}

return \sha1((string) parent::createVertexId($node));
}
}

0 comments on commit 62b011d

Please sign in to comment.