一、二叉树的遍历

以某种特定顺序访问树中所有的节点称为树的遍历,遍历二叉树可分深度优先遍历广度优先遍历
 
广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问节点,访问完一层就进入下一层,直到没有节点访问为止。
深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。可以细分为先序遍历、中序遍历、后序遍历。
深度优先遍历
先序遍历
中序遍历
后序遍历
解释
对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。
即根节点->左子树->右子树。
对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。
即左子树->根节点->右子树。
对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
即左子树->右子树->根节点。
原则
①输出根。
②访问左子树。【先访问左子树中的左子树,再访问左子树中的右子树。】直到访问到叶子节点后输出。
③访问右子树。【先访问右子树中的左子树,再访问右子树中的右子树。】直到访问到叶子节点后输出。
①访问左子树。【先访问左子树中的左子树,再访问左子树中的右子树。】直到访问到叶子节点后输出。
②输出根。
③访问右子树。【先访问右子树中的左子树,再访问右子树中的右子树。】直到访问到叶子节点后输出。
①访问左子树。【先访问左子树中的左子树,再访问左子树中的右子树】。直到访问到叶子节点后输出。
②访问右子树。【先访问右子树中的左子树,再访问右子树中的右子树】。直到访问到叶子节点后输出。
③再返回访问根,并输出。
遍历步骤

A作为根,先输出A。
从A开始,先访问A的左子树。B为左子树的根节点,输出B。B的左子树为D,输出D。D无左右子树,则看B的右子树,为E,输出E。E无左右子树,则A的左子树全部输出完。
 
再访问A的右子树,C为右子树的根节点,输出C。C的左子树为F,输出F。F无左右子树,且C无右子树,A的右子树全部输出完。
A作为根。从A开始,先访问A的左子树。
B的左子树为D,输出D。D无左右子树,则B的左子树已访问完,访问并输出B。再看B的右子树,为E,输出E。E无左右子树,则A的左子树全部输出完,返回并输出A。
 
同理,再看A的右子树。
C的左子树为F,输出F。F无左右子树,则C的左子树已访问完,返回并输出C。C无右子树,则A的右子树全部输出完。
先访问A的左子树。再访问左子树中的左子树。即A的左子树为B,再访问B的左子树D。D没有左右子树,输出D。
然后访问左子树中的右子树。即访问B的右子树E,E没有左右子树,输出E。再输出B。
然后访问A的右子树。再访问右子树中的左子树。即A的右子树为C,再访问C的左子树F。F没有左右子树,输出F。
然后访问右子树中的右子树。即访问C的右子树,C没有右子树,输出C。再输出A。
遍历结果
A(BDE)(CF)
(DBE)A(FC)
(DEB)(FC)A
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

二、PHP用递归、非递归方式实现深度优先遍历二叉树(先序、中序、后序)

1、先序遍历
<?php
class Node {
public $value;
public $left;
public $right;
}
class BT {
// 非递归
// 前序遍历 根节点→左子树→右子树
// 先访问根节点,再遍历左子树,最后遍历右子树;并且在遍历左右子树时,仍需先遍历根节点,然后访问左子树,最后遍历右子树
public function preOrder($root) {
$stack = array();
array_push($stack, $root);
while (!empty($stack)) {
$center_node = array_pop($stack);
echo $center_node->value . " "; // 先输出根节点
if ($center_node->right != null) {
array_push($stack, $center_node->right); // 压入左子树
}
if ($center_node->left != null) {
array_push($stack, $center_node->left);
}
}
} // 递归
// 前序遍历
public function pre_order($root) {
if ($root != null) {
echo $root->value . " "; // 根
if ($root->left != null) {
$this->pre_order($root->left); //递归遍历左树
}
if ($root->right != null) {
$this->pre_order($root->right); //递归遍历右树
}
}
}
}
// 测试
$a = new Node();
$b = new Node();
$c = new Node();
$d = new Node();
$e = new Node();
$f = new Node(); $a->value = "A";
$b->value = "B";
$c->value = "C";
$d->value = "D";
$e->value = "E";
$f->value = "F"; $a->left = $b;
$a->right = $c;
$b->left = $d;
$b->right = $e;
$c->left = $f; $bst = new BT();
echo "----深度优先----";
echo "</br>";
echo "非递归--前序遍历:";
$bst->preOrder($a);
echo "</br>";
echo "递归--前序遍历:";
$bst->pre_order($a);

PHP用递归、非递归方式实现二叉树的先序遍历

2、中序遍历

class Node {
public $value;
public $left;
public $right;
}
class BT {
// 非递归
// 中序遍历
// 左子树→根节点→右子树
public function inOrder($root) {
$stack = array();
$current_node = $root;
while (!empty($stack) || $current_node != null) {
while ($current_node != null) {
array_push($stack, $current_node);
$current_node = $current_node->left;
}
$current_node = array_pop($stack);
echo $current_node->value . " ";
$current_node = $current_node->right;
}
} // 递归
// 中序遍历
public function in_order($root) {
if ($root != null) {
if ($root->left != null) {
$this->in_order($root->left); // 递归遍历左树
}
echo $root->value . " ";
if ($root->right != null) {
$this->in_order($root->right); // 递归遍历右树
}
}
}
} // 测试
$a = new Node();
$b = new Node();
$c = new Node();
$d = new Node();
$e = new Node();
$f = new Node(); $a->value = "A";
$b->value = "B";
$c->value = "C";
$d->value = "D";
$e->value = "E";
$f->value = "F"; $a->left = $b;
$a->right = $c;
$b->left = $d;
$b->right = $e;
$c->left = $f; $bst = new BT(); echo "----深度优先----";
echo "</br>";
echo "非递归--中序遍历:";
$bst->inOrder($a);
echo "</br>";
echo "递归--中序遍历:";
$bst->in_order($a);
echo "</br>";

PHP用递归、非递归方式实现二叉树的中序遍历

3、后序遍历

<?php
class Node {
public $value;
public $left;
public $right;
}
class BT {
// 非递归
// 后序遍历 左子树→右子树→根节点
// 先遍历左子树,然后遍历右子树,最后访问根节点;同样,在遍历左右子树的时候同样要先遍历左子树,然后遍历右子树,最后访问根节点
public function postOrder($root) {
$stack = array();
$out_stack = array();
array_push($stack, $root);
while (!empty($stack)) {
$center_node = array_pop($stack);
array_push($out_stack, $center_node); // 最先压入根节点,最后输出
if ($center_node->left != null) {
array_push($stack, $center_node->left);
}
if ($center_node->right != null) {
array_push($stack, $center_node->right);
}
}
while (!empty($out_stack)) {
$center_node = array_pop($out_stack);
echo $center_node->value . " ";
}
} // 递归
// 后序遍历
public function post_order($root) {
if ($root != null) {
if ($root->left != null) {
$this->post_order($root->left); // 递归遍历左树
}
if ($root->right != null) {
$this->post_order($root->right); // 递归遍历右树
}
echo $root->value . " "; // 根
}
}
} // 测试
$a = new Node();
$b = new Node();
$c = new Node();
$d = new Node();
$e = new Node();
$f = new Node(); $a->value = "A";
$b->value = "B";
$c->value = "C";
$d->value = "D";
$e->value = "E";
$f->value = "F"; $a->left = $b;
$a->right = $c;
$b->left = $d;
$b->right = $e;
$c->left = $f; $bst = new BT(); echo "----深度优先----";
echo "</br>";
echo "非递归--后序遍历:";
$bst->postOrder($a);
echo "</br>";
echo "递归--后序遍历:";
$bst->post_order($a);
echo "</br>";

PHP用递归、非递归方式实现二叉树的后序遍历

三、PHP用递归、非递归方式实现广度优先遍历二叉树

<?php
class Node {
public $value;
public $left;
public $right;
}
class BT {
// 非递归
public function levelOrder($root) {
if ($root == null) {
return;
}
$node = $root;
$queue = array();
array_push($queue, $node); // 根节点入队
while (!empty($queue)) { // 持续输出节点,直到队列为空
$node = array_shift($queue); // 队首元素出队
echo $node->value . " ";
// 左节点先入队
if ($node->left != null) {
array_push($queue, $node->left);
}
// 然后右节点入队
if ($node->right != null) {
array_push($queue, $node->right);
}
}
} // 递归
// 获取树的层数(最大深度)
function getDepth($root) {
if ($root == null) { // 节点为空
return 0;
}
if ($root->left == null && $root->right == null) { // 只有根节点
return 1;
} $left_depth = $this->getDepth($root->left);
$right_depth = $this->getDepth($root->right); return ($left_depth > $right_depth ? $left_depth : $right_depth) + 1;
// return $left_depth > $right_depth ? ($left_depth + 1) : ($right_depth + 1);
} public function level_order($root) {
// 空树或层级不合理
$depth = $this->getDepth($root);
if ($root == null || $depth < 1) {
return;
}
for ($i = 1; $i <= $depth; $i++) {
$this->printTree($root, $i);
}
} public function printTree($root, $level) {
// 空树或层级不合理
if ($root == null || $level < 1) {
return;
}
if ($level == 1) {
echo $root->value;
}
$this->printTree($root->left, $level - 1);
$this->printTree($root->right, $level - 1);
}
} // 测试
$a = new Node();
$b = new Node();
$c = new Node();
$d = new Node();
$e = new Node();
$f = new Node(); $a->value = "A";
$b->value = "B";
$c->value = "C";
$d->value = "D";
$e->value = "E";
$f->value = "F"; $a->left = $b;
$a->right = $c;
$b->left = $d;
$b->right = $e;
$c->left = $f; $bst = new BT();
echo "----广度优先----";
echo "</br>";
echo "非递归:";
$bst->levelOrder($a);
echo "</br>";
echo "递归:";
$bst->level_order($a);

PHP用递归、非递归方式实现二叉树的层次遍历

数据结构与算法之PHP实现二叉树的遍历的更多相关文章

  1. JS数据结构与算法 - 剑指offer二叉树算法题汇总

    ❗❗ 必看经验 在博主刷题期间,基本上是碰到一道二叉树就不会碰到一道就不会,有时候一个下午都在搞一道题,看别人解题思路就算能看懂,自己写就呵呵了.一气之下不刷了,改而先去把二叉树的基础算法给搞搞懂,然 ...

  2. Android版数据结构与算法(六):树与二叉树

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 之前的篇章主要讲解了数据结构中的线性结构,所谓线性结构就是数据与数据之间是一对一的关系,接下来我们就要进入非线性结构的世界了,主要是树与图,好了接 ...

  3. Java数据结构和算法(十)——二叉树

    接下来我们将会介绍另外一种数据结构——树.二叉树是树这种数据结构的一员,后面我们还会介绍红黑树,2-3-4树等数据结构.那么为什么要使用树?它有什么优点? 前面我们介绍数组的数据结构,我们知道对于有序 ...

  4. 数据结构与算法(5)----->二叉树

    1.  概念 二叉树节点的结构: class Node{ int value; // value表示二叉树的节点值 Node left; Node right; // left和right表示二叉树的 ...

  5. Java数据结构和算法(六)--二叉树

    什么是树? 上面图例就是一个树,用圆代表节点,连接圆的直线代表边.树的顶端总有一个节点,通过它连接第二层的节点,然后第二层连向更下一层的节点,以此递推 ,所以树的顶端小,底部大.和现实中的树是相反的, ...

  6. 数据结构与算法(九):AVL树详细讲解

    数据结构与算法(一):基础简介 数据结构与算法(二):基于数组的实现ArrayList源码彻底分析 数据结构与算法(三):基于链表的实现LinkedList源码彻底分析 数据结构与算法(四):基于哈希 ...

  7. javascript数据结构与算法-- 二叉树

    javascript数据结构与算法-- 二叉树 树是计算机科学中经常用到的一种数据结构.树是一种非线性的数据结构,以分成的方式存储数据,树被用来存储具有层级关系的数据,比如文件系统的文件,树还被用来存 ...

  8. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  9. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

随机推荐

  1. CCF计算机网络会议日期

    SenSys: November 5-8 2017, Deadline: April 3, 2017 CoNEXT: December 12-15 2017, Deadline: June 12, 2 ...

  2. ZOJ 3987 Numbers(Java枚举)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3987 题意:给出一个数n,现在要将它分为m个数,这m个数相加起来必须等于n ...

  3. 51nod 1689 逛街(优先队列)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1689 题意: 题意: 枚举终点,这样就确定路上的花费,接下来只需要计算进 ...

  4. Newtonsoft.Json 去掉\r\n

    itemKindList.ToString(Newtonsoft.Json.Formatting.None)

  5. BZOJ 3878 【AHOI2014】 奇怪的计算器

    题目链接:奇怪的计算器 如果没有溢出的话,所有的标记都可以在线段树上直接维护,所以一棵线段树就解决问题了. 现在有了溢出,怎么办呢? 发现就算溢出了,各个元素的相对大小关系也是不变的.所以,如果一开始 ...

  6. Codeforces Round #271 (Div. 2) F. Ant colony 线段树

    F. Ant colony time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  7. Servlet模板,一个供新手参考的模板

    由于这学期老师的进度是刚开始教JavaSE部分,而我的进度比较快,所以买了3本javaee的书,我根据自己的基础,选择了合适的开发实践,另外两本书都和框架相关,我自认为我的web基础还不是很牢固,所以 ...

  8. System.out.println 报错: 只能运行在方法体内哦, 类里面只包含属性和方法哦,注意!

    类里面包含属性和方法 所以, System.out.println,只能放在方法体内运行,不能放在类里.方法外哦

  9. 《剑指offer》第六十八题(树中两个结点的最低公共祖先)

    // 面试题68:树中两个结点的最低公共祖先 // 题目:输入两个树结点,求它们的最低公共祖先. #include <iostream> #include "Tree.h&quo ...

  10. 用aws cli 下载s3中数据到本地

    参考https://blog.csdn.net/DynastyRumble/article/details/76649120 1 首先注册AWS账户,绑定信用卡.一定要填写正确的手机,因为验证方式是它 ...