二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

<?php

namespace app\data_structure\tree;

/**
* php循环方法实现前序、中序、后序遍历二叉树
* 二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)
* https://www.cnblogs.com/rxbook/p/10419365.html
*/ class BinaryTree2
{
public $value;
public $left;
public $right;
} /**
* 前序遍历
* 根节点 ---> 左子树 ---> 右子树
*/
function preorder($root)
{
//PE($root);
$stack = array();
array_push($stack, $root); //将$root(树对象)放入数组$stack中
while (!empty($stack)) {
//删除数组中的最后一个元素,并返回数组的最后一个值,此处$tree返回的就是完整的$root树对象,此时$stack为空
$tree = array_pop($stack);
//PE($tree);
//PE($stack);
echo $tree->value . ' ';//先输出根节点 //由于在循环的过程中,每次array_pop都是删除最后一个元素并返回,因此要先将右子树压进去
if ($tree->right != null) {
array_push($stack, $tree->right);//压入右子树
} //再将左树压进去,这样能保证左树处于最后一个元素,下次循环就会先处理左子树
if ($tree->left != null) {
array_push($stack, $tree->left); //压入左子树
}
//PE($stack);
}
} /**
* 中序遍历
* 左子树---> 根节点 ---> 右子树
*/
function inorder($root)
{
$stack = array();
//最开始,让$tree=最原始的树
$tree = $root;
while (!empty($stack) || $tree != null) {
while ($tree != null) {
//将整个树存入$stack数组中,然后让树变成左子树,依次循环,把全部的左子树存入$stack数组
array_push($stack, $tree);
//直到最后一个左子树,已经没有了left节点,此时$tree为空。相当于把所有层次的树全都压入了$stack数组中
$tree = $tree->left;
}
//P($stack); //从$stack的尾部依次弹出元素并输出,结果就是左子树从最底部到最顶部的值
$tree = array_pop($stack);
echo $tree->value . " "; //此时,将 右子树赋值给 $tree。在没有到达主树之前,所有的右子树都是空,但是$stack不为空。
//也就导致下次内循环的 while($tree != null)不会执行,一直到左子树输出完毕,到达主树(此时$stack为空)。
//由于主树的右子树不为空,从而会执行 while($tree != null),然后会再次将右子树的左子树依次输出,直到输出完最后一个右子树(已经没有了左子树)
$tree = $tree->right;
//PE($tree);
}
} /**
* 后序遍历
* 左子树 ---> 右子树 ---> 根节点
*/
function tailorder($root)
{
$stack = array();
$outstack = array();
array_push($stack, $root);
while (!empty($stack)) {
$tree = array_pop($stack);
array_push($outstack, $tree);//最先压入根节点,最后输出
if ($tree->left != null) {
array_push($stack, $tree->left);
}
if ($tree->right != null) {
array_push($stack, $tree->right);
}
} while (!empty($outstack)) {
$tree = array_pop($outstack);
echo $tree->value . ' ';
}
} //测试
$a = new BinaryTree2();
$b = new BinaryTree2();
$c = new BinaryTree2();
$d = new BinaryTree2();
$e = new BinaryTree2();
$f = new BinaryTree2(); $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;
$c->left = $e;
$c->right = $f; echo "php循环方法实现前序、中序、后序遍历二叉树: \n";
echo "前序遍历:";
preorder($a); //A B D C E F
echo "\n"; echo "中序遍历:";
inorder($a);//D B A E C F
echo "\n"; echo "后序遍历:";
tailorder($a);//D B E F C A
echo "\n";

结果:

A B D C E F


D B A E C F


D B E F C A

php循环方法实现先序、中序、后序遍历二叉树的更多相关文章

  1. DS Tree 已知先序、中序 => 建树 => 求后序

    参考:二叉树--前序和中序得到后序 思路历程: 在最初敲的时候,经常会弄混preorder和midorder的元素位置.大体的思路就是在preorder中找到根节点(根节点在序列的左边),然后在mid ...

  2. 已知树的前序、中序,求后序的java实现&已知树的后序、中序,求前序的java实现

    public class Order { int findPosInInOrder(String str,String in,int position){ char c = str.charAt(po ...

  3. TZOJ 3209 后序遍历(已知中序前序求后序)

    描述 在数据结构中,遍历是二叉树最重要的操作之一.所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问. 这里给出三种遍历算法. 1.中序遍历的递归算法定义:  ...

  4. [Java]算术表达式求值之二(中序表达式转后序表达式方案,支持小数)

    Inlet类,入口类,这个类的主要用途是验证用户输入的算术表达式: package com.hy; import java.io.BufferedReader; import java.io.IOEx ...

  5. [Java]算术表达式求值之一(中序表达式转后序表达式方案)

    第二版请见:https://www.cnblogs.com/xiandedanteng/p/11451359.html 入口类,这个类的主要用途是粗筛用户输入的算术表达式: package com.h ...

  6. LeetCode:二叉树的前、中、后序遍历

    描述: ------------------------------------------------------- 前序遍历: Given a binary tree, return the pr ...

  7. 【数据结构】二叉树的遍历(前、中、后序及层次遍历)及leetcode107题python实现

    文章目录 二叉树及遍历 二叉树概念 二叉树的遍历及python实现 二叉树的遍历 python实现 leetcode107题python实现 题目描述 python实现 二叉树及遍历 二叉树概念 二叉 ...

  8. 分别求二叉树前、中、后序的第k个节点

    一.求二叉树的前序遍历中的第k个节点 //求先序遍历中的第k个节点的值 ; elemType preNode(BTNode *root,int k){ if(root==NULL) return ' ...

  9. HDU 1710 (二叉树的前序和中序,求后序)

    题目链接 题目大意: 输入二叉树的前序.中序遍历,请输出它的后序遍历 #include <stdio.h> #include <string.h> ; // 长度为n s1 前 ...

  10. HDU 1710Binary Tree Traversals(已知前序中序,求后序的二叉树遍历)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1710 解题思路:可以由先序和中序的性质得到 : 先序的第一个借点肯定是当前子树的根结点, 那么在 中序 ...

随机推荐

  1. JVM的内存划分以及常用参数

    JVM的主要划分为: 堆内存,虚拟机栈,方法区,程序计数器,本地方法栈 堆内存: 这部分区域是各个线程共享的,java的大部分对象都是储存在堆中. 1.堆在分配对象内存区域的时候可以分为两种,第一种叫 ...

  2. Spring MVC Redis 整合笔记

    extends:http://blog.csdn.net/defonds/article/details/48716161, http://blog.csdn.net/java2000_wl/arti ...

  3. i.e., e.g., etc.

    经常搞混的一些英语缩写,以及他们的应用规范. i.e. (id est) 含义为:也就是说,that is to say, in other words e.g. (exampli gratia) 含 ...

  4. day_4.30 py

    2018-4-30 13:02:32 ''' 多态:只有当调用方法的时候才知道调用父类 还是子类的方法(随变化而变化,等到真正实行的时候才知道结果) 面向对象三个特点: 封装 继承 多态 ''' cl ...

  5. F#周报2018年第52期

    新闻 Sudokube--使用Fable开发的数独立方体 Rust 2019年及以后的发展 视频及幻灯片 我爱F#代码 马蒂亚斯·布兰在Developer On Fire上的演讲--有条理的和有趣的 ...

  6. .NET Core开发日志——视图与页面

    当一个Action完成它的任务后,通常需要返回一个实现IActionResult的对象,而最常见的就是View或者ViewResult,所谓的视图对象.那么视图与最终所看到的页面之间的联系又是怎样形成 ...

  7. [knowledge] netmap

    900MHz的单核处理10GB的包收/发. netmap has been implemented in FreeBSD and Linux and Gbit/s network adapters. ...

  8. 《linux 字符处理》- grep/sort/uniq/tr/paste

    一:基本 字符处理主要是文本的搜索和处理. 搜索也主要使用到了 管道 作为媒介. 二: grep 搜索文本 基本语法 * grep [-incv] ’文本’ 文件 * i 不区分大小写 * c 匹配行 ...

  9. Java+selenium 如何操作日历控件

    场景:一般的日期控件都是input标签下弹出来的,如果使用webdriver 去设置日期, 1. 定位到该input 2. 使用sendKeys 方法 但是,有的日期控件是readonly的 ,比如神 ...

  10. 重写Object的equals方法

    Object的equals比较两个对象是否相同,没有重写时比较的是内存地址是否相同(==). 但我们有时候比较的是两个对象中的属性是否相同, 重写equals: package cn.sasa.dem ...