Breadth-First-Search 在 PHP
Breadth-First-Search in PHP
我的table结构是:
id name parent lft rgt
1 abc 0 2 3
2 def 1 4 5
3 geh 1 6 7
4 ijk 2 8 9
5 lmn 2 10 11
我正在做的是首先获取所有记录,然后使用深度优先搜索 (DFS) 搜索所有可能的树 children。
public function fetchRecursive($src_arr, $currentId, $parentFound = false)
{
$cats = array();
foreach ($src_arr as $row) {
if ((!$parentFound && $row['id'] == $currentId) || $row['parent'] == $currentId) {
$rowData = array();
foreach ($row as $k => $v)
$rowData[$k] = $v;
$cats[] = $rowData;
if ($row['parent'] == $currentId) {
$cats = array_merge($cats, $this->fetchRecursive($src_arr, $row['id'], true));
}
}
}
return $cats;
}
此函数工作正常并返回节点的所有 children。
我正在寻找的是一种使用 BFS 获取节点所有 children 的方法?
BFS并不是要得到所有的子节点,BFS是寻找从节点s到节点t的最短路径。
DFS 如何访问所有节点,这似乎更像是您正在尝试做的事情。
还请记住,BFS 不会转到无法从节点 S 访问的节点。
BFS 成本为 O(E + V)(大多数情况)
DFS 成本也是 O(E + V)
这意味着您使用 BFS 不会有任何附加值,我建议坚持使用 DFS,它对您的目的更有效。
我自己写了BFS搜索功能。我用了 PHP's SplQueue
用于存储子数组的全局变量。
Private $queue = [];
BFS 函数
public function traverseTree($rootNode, $dummyQueue)
{
if($rootNode->lft != 0) {
$dummyQueue->enqueue($rootNode->lft);
}
if($rootNode->rgt != 0) {
$dummyQueue->enqueue($rootNode->rgt);
}
if(!($dummyQueue->isEmpty())){
$nextId = $dummyQueue->dequeue();
$nextNode = //get next node information using $nextId
array_push($this->queue, $nextNode);
$this->traverseTree($nextNode, $dummyQueue);
}
}
调用 traverseTree() 函数
$dummyQueue = new \SplQueue();
$this->traverseTree($id, $dummyQueue);
此处 $id 是您要获取其所有子节点的根节点。
我在gist里也添加了一个文件,欢迎提出建议和改进
您也可以使用两个标准数组来执行此操作:
class Node {
protected int $value;
protected ?Node $left;
protected ?Node $right;
public function __construct(int $value, ?Node $left = null, ?Node $right = null) {
$this->value = $value;
$this->left = $left;
$this->right = $right;
}
public function breadth_first() {
$level = [$this];
while (count($level)) {
$next_level = [];
foreach ($level as $node) {
yield $node->value;
if ($node->left) array_push($next_level, $node->left);
if ($node->right) array_push($next_level, $node->right);
}
$level = $next_level;
}
}
}
您可以这样称呼它:
$tree = new Node(1,
new Node(2,
new Node(4),
new Node(5)
),
new Node(3)
);
foreach($tree->breadth_first() as $value) {
echo "$value\n";
}
我的table结构是:
id name parent lft rgt
1 abc 0 2 3
2 def 1 4 5
3 geh 1 6 7
4 ijk 2 8 9
5 lmn 2 10 11
我正在做的是首先获取所有记录,然后使用深度优先搜索 (DFS) 搜索所有可能的树 children。
public function fetchRecursive($src_arr, $currentId, $parentFound = false)
{
$cats = array();
foreach ($src_arr as $row) {
if ((!$parentFound && $row['id'] == $currentId) || $row['parent'] == $currentId) {
$rowData = array();
foreach ($row as $k => $v)
$rowData[$k] = $v;
$cats[] = $rowData;
if ($row['parent'] == $currentId) {
$cats = array_merge($cats, $this->fetchRecursive($src_arr, $row['id'], true));
}
}
}
return $cats;
}
此函数工作正常并返回节点的所有 children。
我正在寻找的是一种使用 BFS 获取节点所有 children 的方法?
BFS并不是要得到所有的子节点,BFS是寻找从节点s到节点t的最短路径。 DFS 如何访问所有节点,这似乎更像是您正在尝试做的事情。 还请记住,BFS 不会转到无法从节点 S 访问的节点。
BFS 成本为 O(E + V)(大多数情况) DFS 成本也是 O(E + V)
这意味着您使用 BFS 不会有任何附加值,我建议坚持使用 DFS,它对您的目的更有效。
我自己写了BFS搜索功能。我用了 PHP's SplQueue
用于存储子数组的全局变量。
Private $queue = [];
BFS 函数
public function traverseTree($rootNode, $dummyQueue)
{
if($rootNode->lft != 0) {
$dummyQueue->enqueue($rootNode->lft);
}
if($rootNode->rgt != 0) {
$dummyQueue->enqueue($rootNode->rgt);
}
if(!($dummyQueue->isEmpty())){
$nextId = $dummyQueue->dequeue();
$nextNode = //get next node information using $nextId
array_push($this->queue, $nextNode);
$this->traverseTree($nextNode, $dummyQueue);
}
}
调用 traverseTree() 函数
$dummyQueue = new \SplQueue();
$this->traverseTree($id, $dummyQueue);
此处 $id 是您要获取其所有子节点的根节点。
我在gist里也添加了一个文件,欢迎提出建议和改进
您也可以使用两个标准数组来执行此操作:
class Node {
protected int $value;
protected ?Node $left;
protected ?Node $right;
public function __construct(int $value, ?Node $left = null, ?Node $right = null) {
$this->value = $value;
$this->left = $left;
$this->right = $right;
}
public function breadth_first() {
$level = [$this];
while (count($level)) {
$next_level = [];
foreach ($level as $node) {
yield $node->value;
if ($node->left) array_push($next_level, $node->left);
if ($node->right) array_push($next_level, $node->right);
}
$level = $next_level;
}
}
}
您可以这样称呼它:
$tree = new Node(1,
new Node(2,
new Node(4),
new Node(5)
),
new Node(3)
);
foreach($tree->breadth_first() as $value) {
echo "$value\n";
}