这次给大家带来的是实现一棵二叉树的深度广度优先遍历的算法步骤详解PHP 中的二叉树。 PHP中实现二叉树的深度和广度优先遍历有哪些注意事项?下面是一个实际案例,我们来看看。
前言:
深度优先遍历:深入每一个可能的分支路径,直到不能再深入为止,每个节点只能被访问一次。需要注意的是,二叉树的深度优先遍历比较特殊,可以细分为前序遍历、中序遍历和后序遍历。具体说明如下:
前序遍历:根节点 -> 左子树 -> 右子树
中序遍历:左子树 -> 根节点 -> 右子树
后序遍历:左子树 -> 右子树-> 根节点
广度优先遍历:也称为分层遍历,从上到下依次访问每一层。在每一层中,节点是从左到右(或从右到左)访问的。访问结束后,一级进入下一级,直到没有节点可以访问为止。
例如,对于这棵树:
/** * 前序遍历(递归方法) */ 私有函数 pre_order1($root) { if (!is_null($root)) { //这里使用常量FUNCTION来获取当前函数名。优点是如果修改了函数名,则不需要修改实现。 $函数=函数; 回显 $root->key 。 “”; $this->$function($root->left); $this->$function($root->right); } } /** * 前序遍历(非递归方法) * 因为遍历完根节点还要回来,所以必须保存。考虑到后进先出的特点,选择栈存储。 */ 私有函数 pre_order2($root) {}
注:1.我把所有的遍历方法封装在一个类遍历中。 2.在pre_order2方法中,使用堆栈时,我使用的是PHP标准库SPL提供的splstack。如果习惯使用数组,可以使用 array_push()
和 array_pop()
模拟实现。
2。中序遍历:
/** * 中序遍历(递归方法) */ 私有函数 mid_order1($root) { if (!is_null($root)) { $函数=函数; $this->$function($root->left); 回显 $root->key 。 “”; $this->$function($root->right); } } /** * 中序遍历(非递归方法) * 因为遍历完根节点还要回来,所以必须保存。考虑到后进先出的特点,选择栈存储。 */ 私有函数 mid_order2($root) { 如果 (is_null($root)) { 返回; } $stack = new splstack(); $节点=$根; while (!is_null($node) || !$stack->isEmpty()) { while (!is_null($node)) { $stack->push($node); $node = $node->左; } $node = $stack->pop(); 回显 $node->key 。 ' '; $node = $node->右; } } //中序遍历 公共函数 MidOrder() {// $this->mid_order1($this->tree->root); $this->mid_order2($this->tree->root); }
3.后序遍历:
/** * 后序遍历(递归方法) */ 私有函数 post_order1($root) { if (!is_null($root)) { $函数=函数; $this->$function($root->left); $this->$function($root->right); 回显 $root->key 。 “”; } } /** * 后序遍历(非递归方法) * 因为遍历完根节点还要回来,所以必须保存。考虑到后进先出的特点,选择栈存储。 * 由于访问左子节点后很难跳转到右子节点,所以这里使用了一个标记lastVisited来标识最后访问的节点。 */ 私有函数 post_order2($root) { 如果 (is_null($root)) { 返回; } $节点=$根; $stack = new splstack(); //保存最后访问的节点引用 $lastVisited = NULL; $stack->push($node); while(!$stack->isEmpty()){ $node = $stack->top();//获取栈顶元素,但不弹出 if(($node->left == NULL && $node->right == NULL) || ($node->right == NULL && $lastVisited == $node->left) || ($lastVisited == $节点->右)){ 回显 $node->key。' ';$lastVisited = $node; $stack->pop(); }别的{ if($node->右){ $stack->push($node->right); } if($node->左){ $stack->push($node->left); } } } } //后序遍历 公共函数 PostOrder() { // $this->post_order1($this->tree->root); $this->post_order2($this->tree->root); }
广度优先遍历:
1。关卡遍历:
/** * 层级遍历(递归方法) * 由于是逐层遍历,所以传递的是树的层数 */ 私有函数 level_order1($root,$level){ if($root == NULL || $level < 1){ 返回; } 如果($级别== 1){ 回显 $root->key。' '; 返回; } if(!is_null($root->left)){ $this->level_order1($root->left,$level - 1); } if(!is_null($root->right)){ $this->level_order1($root->right,$level - 1); } } /** * 层级遍历(非递归方法) *每层输出从左到右 元素的存储需要具有先进先出的特性,因此采用队列存储。 */ 私有函数 level_order2($root){ 如果(is_null($root)){返回; } $节点=$根; // 利用队列实现 // $queue = array(); // array_push($queue,$node); // // while(!is_null($node = array_shift($queue))){ // 回显 $node->key。' '; // if(!is_null($node->left)){ // array_push($queue,$node->left); // } // if(!is_null($node->right)){ // array_push($queue,$node->right); // } // } $queue = new splqueue(); $queue->enqueue($node); while(!$queue->isEmpty()){ $node = $queue->dequeue(); 回显 $node->key。' '; if (!is_null($node->left)) { $queue->enqueue($node->left); } if (!is_null($node->right)) { $queue->enqueue($node->right); } } } // 层次遍历 公共函数 LevelOrder(){ // $level = $this->getdepth($this->tree->root); // for($i = 1;$i <= $level;$i ++){ // $this->level_order1($this->tree->root,$i); // } $this->level_order2($this->tree->root);} //获取树的层数 私有函数 getDepth($root){ 如果(is_null($root)){ 返回0; } $left = getdepth($root -> left); $right = getdepth($root -> right); $深度 = ($left > $right ? $left : $right) + 1; 返回$深度; }
注意:level_order2方法中,使用队列时,我使用的是PHP标准库SPL提供的splqueue。如果习惯使用数组,可以使用 array_push()
和 array_shift()
模拟实现。
用途:
现在我们看一下客户端代码:
类客户端 { 公共静态函数 Main() { 尝试 { //实现文件的自动加载 函数自动加载($class) { 包括 strtolower($class) 。 '.php'; } spl_autoload_register('自动加载'); $arr = 数组(10, 8, 12, 7, 9, 11, 13); $tree = new Bst(); // $tree = new Avl(); // $tree = new Rbt(); $tree->init($arr); $traverse = 新的遍历($tree); $traverse->PreOrder(); // $traverse->MidOrder(); // $traverse->PostOrder();// $traverse->LevelOrder(); } catch (异常$e) { 回声 $e->getMessage(); } } } 客户端::Main();
补充:
1。客户端使用的Bst、Avl、Rbt这三个类可以参考之前的文章:《PHP实现绘制二叉树图形显示功能详解》
2。为什么我推荐大家使用SPL标准库中提供的splstack
和splqueue
?这是我在一篇文章中看到的:虽然我们可以使用传统的变量类型来描述数据结构,比如使用数组来描述栈(Strack)——然后使用相应的方法pop和push(array_pop(;SPL的SplStack对象)严格以栈的形式描述数据,并提供相应的方法,同时这样的代码也应该能够理解是在栈上操作而不是数组,让同行更好的理解相应的代码,并且会更快,原文地址:PHP SPL,失落的宝石
相信看完本文的案例你已经掌握了方法。更多精彩资讯请关注其他相关文章!
推荐阅读:
PHP简单选择排序案例详解
PHP实现Huffman编码/解码的步骤详解