Skip to content

Commit

Permalink
Merge pull request #7 from dc-ag/mb/early-traversal-termination
Browse files Browse the repository at this point in the history
Mb/early traversal termination
  • Loading branch information
MBauerDC committed Jan 25, 2022
2 parents 15169f5 + b824734 commit 8c072eb
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/EarlyTraversalTerminationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);

namespace TreeNodes;

use Exception;

class EarlyTraversalTerminationException extends Exception {}
4 changes: 3 additions & 1 deletion src/GenericTreeNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function visitPreOrder(?SortableTreeNode $node, bool $atRoot = true): voi
}
($this->visitorCallable)($node);
$this->visitPreOrder($leftmostChild, false);

if (!$atRoot) {
$this->visitPreOrder($node->getRightSibling(), false);
}
Expand Down Expand Up @@ -67,6 +68,7 @@ public function visitPostOrder(?SortableTreeNode $node, bool $atRoot = true): vo
if (!$atRoot) {
$this->visitPostOrder($node->getRightSibling(), false);
}

}

/**
Expand All @@ -88,7 +90,6 @@ public function visitLevelOrder(?SortableTreeNode $node, bool $atRoot = true): v
$collectNextLevelNodes = static function(SortableTreeNode $treeNode) use (&$nextLevelNodes) {
$nextLevelNodes = [...$nextLevelNodes, ...$treeNode->getChildren()];
};

do {
while (!empty($currlevelNodes)) {
$currNode = \array_shift($currlevelNodes);
Expand All @@ -98,5 +99,6 @@ public function visitLevelOrder(?SortableTreeNode $node, bool $atRoot = true): v
$currlevelNodes = $nextLevelNodes;
$nextLevelNodes = [];
} while (!empty($currlevelNodes));

}
}
66 changes: 66 additions & 0 deletions tests/Unit/GenericTreeNodeVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use TreeNodes\TreeNodeVisitor;
use TreeNodes\GenericTreeNodeVisitor;
use TreeNodes\SortableTreeNode;
use TreeNodes\EarlyTraversalTerminationException;

final class GenericTreeNodeVisitorTest extends TestCase
{
Expand Down Expand Up @@ -105,4 +106,69 @@ public function testVisitLevelOrder(): void
$errMsg = 'Expected order: [' . $expectedOrder . '] - actual order [' . $this->orderString . '].';
$this->assertEquals($expectedOrder, $this->orderString, $errMsg);
}


public function testEarlyPreOrderTraversalTermination(): void
{
$sortableTreeNode = $this->demoTree;
$this->orderString = "";
$expectedOrder = "root, 1, 2, 2.1";
$visitFn = function(SortableTreeNode $treeNode) {
$separator = '' === $this->orderString ? '' : ', ';
$id = $treeNode->getId();
$this->orderString .= $separator . $id;
if ('2.1' === $id) {
throw new EarlyTraversalTerminationException();
}
};
$visitor = new GenericTreeNodeVisitor($visitFn);
try {
$visitor->visitPreOrder($sortableTreeNode);
} catch (EarlyTraversalTerminationException) {}
$errMsg = 'Expected order: [' . $expectedOrder . '] - actual order [' . $this->orderString . '].';
$this->assertEquals($expectedOrder, $this->orderString, $errMsg);
}

public function testEarlyPostOrderTraversalTermination(): void
{
$sortableTreeNode = $this->demoTree;
$this->orderString = "";
$expectedOrder = "1, 2.1.1, 2.1.2, 2.1";
$visitFn = function(SortableTreeNode $treeNode) {
$separator = '' === $this->orderString ? '' : ', ';
$id = $treeNode->getId();
$this->orderString .= $separator . $id;
if ('2.1' === $id) {
throw new EarlyTraversalTerminationException();
}
};
$visitor = new GenericTreeNodeVisitor($visitFn);
try {
$visitor->visitPostOrder($sortableTreeNode);
} catch (EarlyTraversalTerminationException) {}

$errMsg = 'Expected order: [' . $expectedOrder . '] - actual order [' . $this->orderString . '].';
$this->assertEquals($expectedOrder, $this->orderString, $errMsg);
}

public function testEarlyLevelOrderTraversalTermination(): void
{
$sortableTreeNode = $this->demoTree;
$this->orderString = "";
$expectedOrder = "root, 1, 2, 3, 4, 5, 2.1";
$visitFn = function(SortableTreeNode $treeNode) {
$separator = '' === $this->orderString ? '' : ', ';
$id = $treeNode->getId();
$this->orderString .= $separator . $id;
if ('2.1' === $id) {
throw new EarlyTraversalTerminationException();
}
};
$visitor = new GenericTreeNodeVisitor($visitFn);
try {
$visitor->visitLevelOrder($sortableTreeNode);
} catch (EarlyTraversalTerminationException) {}
$errMsg = 'Expected order: [' . $expectedOrder . '] - actual order [' . $this->orderString . '].';
$this->assertEquals($expectedOrder, $this->orderString, $errMsg);
}
}

0 comments on commit 8c072eb

Please sign in to comment.