当前位置: 首页 > news >正文

php 实现二叉树的最大深度_PHP实现二叉树的深度优先遍历(前序、中序、后序)和广度优先遍历(层次)...

优质文章第一时间送达!

前言:

深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历。具体说明如下:

前序遍历:根节点->左子树->右子树

中序遍历:左子树->根节点->右子树

后序遍历:左子树->右子树->根节点

广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。

例如对于一下这棵树:

深度优先遍历:

前序遍历:10 8 7 9 12 11 13

中序遍历:7 8 9 10 11 12 13

后序遍历:7 9 8 11 13 12 10

广度优先遍历:

层次遍历:10 8 12 7 9 11 13

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

深度优先遍历:

1、前序遍历:

/*** 前序遍历(递归方法)*/private function pre_order1($root){if (!is_null($root)) {//这里用到常量__FUNCTION__,获取当前函数名,好处是假如修改函数名的时候,里面的实现不用修改$function = __FUNCTION__;echo $root->key . " ";$this->$function($root->left);$this->$function($root->right);}}/*** 前序遍历(非递归方法)* 因为当遍历过根节点之后还要回来,所以必须将其存起来。考虑到后进先出的特点,选用栈存储。*/private function pre_order2($root){// $stack = new splstack();// $stack->push($root);// while(!$stack->isEmpty()){// $node = $stack->pop();// echo $node->key.' ';// if(!is_null($node->right)){// $stack->push($node->right);// }// if(!is_null($node->left)){// $stack->push($node->left);// }// }if (is_null($root)) {return;}$stack = new splstack();$node = $root;while (!is_null($node) || !$stack->isEmpty()) {while (!is_null($node)) {//只要结点不为空就应该入栈保存,与其左右结点无关$stack->push($node);echo $node->key . ' ';$node = $node->left;}$node = $stack->pop();$node = $node->right;}}//前序遍历public function PreOrder(){// 所在对象中的tree属性保存了一个树的引用// $this->pre_order1($this->tree->root);$this->pre_order2($this->tree->root);}

说明:1、我将所有的遍历方法都封装在一个类 traverse 里面了。2、pre_order2方法中,在使用栈的过程中,我使用的是PHP标准库SPL提供的splstack,如果你们习惯使用数组的话,可以使用 array_push() 和array_pop() 模拟实现。

2、中序遍历:

/*** 中序遍历(递归方法)*/private function mid_order1($root){if (!is_null($root)) {$function = __FUNCTION__;$this->$function($root->left);echo $root->key . " ";$this->$function($root->right);}}/*** 中序遍历(非递归方法)* 因为当遍历过根节点之后还要回来,所以必须将其存起来。考虑到后进先出的特点,选用栈存储。*/private function mid_order2($root){if (is_null($root)) {return;}$stack = new splstack();$node = $root;while (!is_null($node) || !$stack->isEmpty()) {while (!is_null($node)) {$stack->push($node);$node = $node->left;}$node = $stack->pop();echo $node->key . ' ';$node = $node->right;}}//中序遍历public function MidOrder(){// $this->mid_order1($this->tree->root);$this->mid_order2($this->tree->root);}

3、后序遍历:

/*** 后序遍历(递归方法)*/private function post_order1($root){if (!is_null($root)) {$function = __FUNCTION__;$this->$function($root->left);$this->$function($root->right);echo $root->key . " ";}}/*** 后序遍历(非递归方法)* 因为当遍历过根节点之后还要回来,所以必须将其存起来。考虑到后进先出的特点,选用栈存储。* 由于在访问了左子节点后怎么跳到右子节点是难点,这里使用一个标识lastVisited来标识上一次访问的结点*/private function post_order2($root){if (is_null($root)) {return;}$node = $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->right)){echo $node->key.' ';$lastVisited = $node;$stack->pop();}else{if($node->right){$stack->push($node->right);}if($node->left){$stack->push($node->left);}}}}//后序遍历public function PostOrder(){// $this->post_order1($this->tree->root);$this->post_order2($this->tree->root);}

广度优先遍历:

1、层次遍历:

/*** 层次遍历(递归方法)* 由于是按层逐层遍历,因此传递树的层数*/private function level_order1($root,$level){if($root == NULL || $level < 1){return;}if($level == 1){echo $root->key.' ';return;}if(!is_null($root->left)){$this->level_order1($root->left,$level - 1);}if(!is_null($root->right)){$this->level_order1($root->right,$level - 1);}}/*** 层次遍历(非递归方法)* 每一层从左向右输出元素需要储存有先进先出的特性,所以选用队列存储。*/private function level_order2($root){if(is_null($root)){return;}$node = $root;//利用队列实现// $queue = array();// array_push($queue,$node); while(!is_null($node = array_shift($queue))){// echo $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();echo $node->key.' ';if (!is_null($node->left)) {$queue->enqueue($node->left);}if (!is_null($node->right)) {$queue->enqueue($node->right);}}}//层次遍历public function 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);}//获取树的层数private function getdepth($root){if(is_null($root)){return 0;}$left = getdepth($root -> left);$right = getdepth($root -> right);$depth = ($left > $right ? $left : $right) + 1;return $depth;}

说明:level_order2方法中,在使用队列的过程中,我使用的是PHP标准库SPL提供的splqueue,如果你们习惯使用数组的话,可以使用 array_push() 和array_shift() 模拟实现。

使用:

现在我们来看看客户端代码:

class Client{public static function Main(){try {//实现文件的自动加载function autoload($class){include strtolower($class) . '.php';}spl_autoload_register('autoload');$arr = array(10, 8, 12, 7, 9, 11, 13);$tree = new Bst();// $tree = new Avl();// $tree = new Rbt();$tree->init($arr);$traverse = new traverse($tree);$traverse->PreOrder();// $traverse->MidOrder();// $traverse->PostOrder();// $traverse->LevelOrder();} catch (Exception $e) {echo $e->getMessage();}}}CLient::Main();

相关文章:

  • sap客户信贷_企业客户信用控制管理机制实践(2/2)
  • 晶闸管有几个pn结_【半导体物理】PN结
  • 模板文字修改_ppt模板适用于室内装修设计的图片展示国片混排等演示PPT模版
  • 机器学习预测时间序列 特征值怎么确定_AWS发布时间序列预测云服务,无机器学习基础也能上手...
  • mybatis 二级缓存失效_Mybatis 一二级缓存实现原理与使用指南
  • pycharm导入mysql_Pycharm创建Django项目讲解 python django
  • fanuc机器人控制柜接线_FANUC机器人系统镜像还原步骤
  • zabbix监控磁盘_zabbix监控cpu、内存、磁盘使用情况
  • 一直跳动的按钮插件_职场表格插件 Power Click功能介绍03:工作便签
  • 手机屏幕常见故障_华强北二手苹果手机面容损坏可修复原理(重磅,大家务必小心,莫贪小便宜)...
  • springcloud 创建子父项目_SpringCloud(四)- 父子项目
  • redis常用命令getex_详解Redis基本命令
  • 需要显卡还是cpu_组装电脑装机预算不足的情况下,选择高U低显还是高显低U?...
  • 云计算体系结构中soa构建层_云计算体系结构
  • 编译安装_CentOS 7 源码编译安装Python3.9
  • Brief introduction of how to 'Call, Apply and Bind'
  • C++入门教程(10):for 语句
  • Consul Config 使用Git做版本控制的实现
  • CSS 专业技巧
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • Laravel 菜鸟晋级之路
  • mac修复ab及siege安装
  • session共享问题解决方案
  • Spring Cloud中负载均衡器概览
  • Spring-boot 启动时碰到的错误
  • SQLServer之索引简介
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • supervisor 永不挂掉的进程 安装以及使用
  • V4L2视频输入框架概述
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • win10下安装mysql5.7
  • 闭包,sync使用细节
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 你不可错过的前端面试题(一)
  • 使用parted解决大于2T的磁盘分区
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (26)4.7 字符函数和字符串函数
  • (二)斐波那契Fabonacci函数
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (过滤器)Filter和(监听器)listener
  • (三)终结任务
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (原)本想说脏话,奈何已放下
  • (转)shell中括号的特殊用法 linux if多条件判断
  • ***检测工具之RKHunter AIDE
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net 按比例显示图片的缩略图