PHP实现的线索二叉树及二叉树遍历方法详解


Posted in PHP onApril 25, 2016

本文实例讲述了PHP实现的线索二叉树及二叉树遍历方法。分享给大家供大家参考,具体如下:

<?php
  require 'biTree.php';
  $str = 'ko#be8#tr####acy#####';
  $tree = new BiTree($str);
  $tree->createThreadTree();
  echo $tree->threadList() . "\n";从第一个结点开始遍历线索二叉树
  echo $tree->threadListReserv();从最后一个结点开始反向遍历
?>

biTree.php:

<?
  /**
   * PHP实现二叉树
   *
   * @author zhaojiangwei
   * @since 2011/10/25 10:32
   */
  //结点类
  class Node{
    private $data = NULL;
    private $left = NULL;
    private $right = NULL;
    private $lTag = 0;
    private $rTag = 0;
    public function Node($data = false){
      $this->data = $data;
    }
    //我不喜欢使用魔术方法
    public function getData(){
      return $this->data;
    }
    public function setData($data){
      $this->data = $data;
    }
    public function getLeft(){
      return $this->left;
    }
    public function setLeft($left){
      $this->left = $left;
    }
    public function getRight(){
      return $this->right;
    }
    public function setRight($right){
      $this->right = $right;
    }
    public function getLTag(){
      return $this->lTag;
    }
    public function setLTag($tag){
      $this->lTag = $tag;
    }
    public function getRTag(){
      return $this->rTag;
    }
    public function setRTag($tag){
      $this->rTag = $tag;
    }
  }
  //线索二叉树类
  class BiTree{
    private $datas = NULL;//要导入的字符串;
    private $root = NULL; //根结点
    private $leafCount = 0;//叶子结点个数
    private $headNode = NULL; //线索二叉树的头结点
    private $preNode = NULL;//遍历线索化二叉树时保存前一个遍历的结点
    public function BiTree($datas){
      is_array($datas) || $datas = str_split($datas);
      $this->datas = $datas;
      $this->backupData = $this->datas;
      $this->createTree(TRUE);
    }
    //前序遍历创建树
    //$root 判断是不是要创建根结点
    public function createTree($root = FALSE){
      if(emptyempty($this->datas)) return NULL;
      $first = array_shift($this->datas);
      if($first == '#'){
        return NULL;
      }else{
        $node = new Node($first);
        $root && $this->root = $node;
        $node->setLeft($this->createTree());
        $node->setRight($this->createTree());
        return $node;
      }
    }
    //返回二叉树叶子结点的个数
    public function getLeafCount(){
      $this->figureLeafCount($this->root);
      return $this->leafCount;
    }
    private function figureLeafCount($node){
      if($node == NULL)
        return false;
      if($this->checkEmpty($node)){
        $this->leafCount ++;
      }else{
        $this->figureLeafCount($node->getLeft());
        $this->figureLeafCount($node->getRight());
      }
    }
    //判断结点是不是叶子结点
    private function checkEmpty($node){
      if($node->getLeft() == NULL && $node->getRight() == NULL){
        return true;
      }
      return false;
    }
    //返回二叉树深度
    public function getDepth(){
      return $this->traversDepth($this->root);
    }
    //遍历求二叉树深度
    public function traversDepth($node){
      if($node == NULL){
        return 0;
      }
      $u = $this->traversDepth($node->getLeft()) + 1;
      $v = $this->traversDepth($node->getRight()) + 1;
      return $u > $v ? $u : $v;
    }
    //返回遍历结果,以字符串的形式
    //$order 按遍历形式返回,前中后
    public function getList($order = 'front'){
      if($this->root == NULL) return NULL;
      $nodeList = array();
      switch ($order){
        case "front":
          $this->frontList($this->root, $nodeList);
          break;
        case "middle":
          $this->middleList($this->root, $nodeList);
          break;
        case "last":
          $this->lastList($this->root, $nodeList);
          break;
        default:
          $this->frontList($this->root, $nodeList);
          break;
      }
      return implode($nodeList);
    }
    //创建线索二叉树
    public function createThreadTree(){
      $this->headNode = new Node();
      $this->preNode = & $this->headNode;
      $this->headNode->setLTag(0);
      $this->headNode->setLeft($this->root);
      $this->headNode->setRTag(1);
      $this->threadTraverse($this->root);
      $this->preNode->setRight($this->headNode);
      $this->preNode->setRTag(1);
      $this->headNode->setRight($this->preNode);
    }
    //线索化二叉树
    private function threadTraverse($node){
      if($node != NULL){
        if($node->getLeft() == NULL){
          $node->setLTag(1);
          $node->setLeft($this->preNode);
        }else{
          $this->threadTraverse($node->getLeft());
        }
        if($this->preNode != $this->headNode && $this->preNode->getRight() == NULL){
          $this->preNode->setRTag(1);
          $this->preNode->setRight($node);
        }
        $this->preNode = & $node;//注意传引用
        $this->threadTraverse($node->getRight());
      }
    }
    //从第一个结点遍历中序线索二叉树
    public function threadList(){
      $arr = array();
      for($node = $this->getFirstThreadNode($this->root); $node != $this->headNode; $node = $this->getNextNode($node)){
        $arr[] = $node->getData();
      }
      return implode($arr);
    }
    //从尾结点反向遍历中序线索二叉树
    public function threadListReserv(){
      $arr = array();
      for($node = $this->headNode->getRight(); $node != $this->headNode; $node = $this->getPreNode($node)){
        $arr[] = $node->getData();
      }
      return implode($arr);
    }
    //返回某个结点的前驱
    public function getPreNode($node){
      if($node->getLTag() == 1){
        return $node->getLeft();
      }else{
        return $this->getLastThreadNode($node->getLeft());
      }
    }
    //返回某个结点的后继
    public function getNextNode($node){
      if($node->getRTag() == 1){
        return $node->getRight();
      }else{
        return $this->getFirstThreadNode($node->getRight());
      }
    }
    //返回中序线索二叉树的第一个结点
    public function getFirstThreadNode($node){
      while($node->getLTag() == 0){
        $node = $node->getLeft();
      }
      return $node;
    }
    //返回中序线索二叉树的最后一个结点
    public function getLastThreadNode($node){
      while($node->getRTag() == 0){
        $node = $node->getRight();
      }
      return $node;
    }
    //前序遍历
    private function frontList($node, & $nodeList){
      if($node !== NULL){
        $nodeList[] = $node->getData();
        $this->frontList($node->getLeft(), $nodeList);
        $this->frontList($node->getRight(), $nodeList);
      }
    }
    //中序遍历
    private function middleList($node, & $nodeList){
      if($node != NULL){
        $this->middleList($node->getLeft(), $nodeList);
        $nodeList[] = $node->getData();
        $this->middleList($node->getRight(), $nodeList);
      }
    }
    //后序遍历
    private function lastList($node, & $nodeList){
      if($node != NULL){
        $this->lastList($node->getLeft(), $nodeList);
        $this->lastList($node->getRight(), $nodeList);
        $nodeList[] = $node->getData();
      }
    }
    public function getData(){
      return $this->data;
    }
    public function getRoot(){
      return $this->root;
    }
  }
?>

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php miniBB中文乱码问题解决方法
Nov 25 PHP
php设计模式 Builder(建造者模式)
Jun 26 PHP
PHP 利用AJAX获取网页并输出的实现代码(Zjmainstay)
Aug 31 PHP
php url路由入门实例
Apr 23 PHP
PHP+memcache实现消息队列案例分享
May 21 PHP
PHP中执行cmd命令的方法
Oct 11 PHP
php之readdir函数用法实例
Nov 13 PHP
在php和MySql中计算时间差的方法详解
Mar 27 PHP
php实现的日历程序
Jun 18 PHP
分析PHP中单双引号的误区和双引号小隐患
Jul 19 PHP
PHP接收App端发送文件流的方法
Sep 23 PHP
php新建文件的方法实例
Sep 26 PHP
PHP简单实现生成txt文件到指定目录的方法
Apr 25 #PHP
PHP的全局错误处理详解
Apr 25 #PHP
PHP预定义变量9大超全局数组用法详解
Apr 23 #PHP
php构造函数与析构函数
Apr 23 #PHP
浅谈PHP中的
Apr 23 #PHP
简单谈谈PHP中的include、include_once、require以及require_once语句
Apr 23 #PHP
浅析Yii2 gridview实现批量删除教程
Apr 22 #PHP
You might like
15个小时----从修改程序到自己些程序
2006/10/09 PHP
php上传文件并显示上传进度的方法
2015/03/24 PHP
php根据日期或时间戳获取星座信息和生肖等信息
2015/10/20 PHP
Fleaphp常见函数功能与用法示例
2016/11/15 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
PHP5.6.8连接SQL Server 2008 R2数据库常用技巧分析总结
2019/05/06 PHP
PHP设计模式(五)适配器模式Adapter实例详解【结构型】
2020/05/02 PHP
通过JS获取用户本地图片路径并显示的代码
2012/02/16 Javascript
通过js动态操作table(新增,删除相关列信息)
2012/05/23 Javascript
利用js 进行输入框自动匹配字符的小例子
2013/06/29 Javascript
jQuery显示和隐藏 常用的状态判断方法
2015/01/29 Javascript
关于JavaScript作用域你想知道的一切
2016/02/04 Javascript
Bootstrap基本组件学习笔记之导航(10)
2016/12/07 Javascript
Linux系统中利用node.js提取Word(doc/docx)及PDF文本的内容
2017/06/17 Javascript
vue中appear的用法
2017/08/17 Javascript
微信小程序使用component自定义toast弹窗效果
2018/11/27 Javascript
浅析vue中的MVVM实现原理
2019/03/04 Javascript
jquery向后台提交数组的代码分析
2020/02/20 jQuery
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
Python中文件I/O高效操作处理的技巧分享
2017/02/04 Python
Tornado协程在python2.7如何返回值(实现方法)
2017/06/22 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
Python实现 PS 图像调整中的亮度调整
2019/06/28 Python
解决Django 在ForeignKey中出现 non-nullable field错误的问题
2019/08/06 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
python怎么判断素数
2020/07/01 Python
英国高级百货公司:Harvey Nichols
2017/01/29 全球购物
高品质和独特的产品世界:Creations and Collections
2018/01/07 全球购物
教育学专业实习生的自我鉴定
2013/11/26 职场文书
护士长竞聘书
2014/03/31 职场文书
学雷锋志愿者活动总结
2014/06/27 职场文书
2014国庆节幼儿园亲子活动方案
2014/09/16 职场文书
小学生差生评语
2014/12/29 职场文书
高中班主任评语
2014/12/30 职场文书
青年志愿者服务活动总结
2015/05/06 职场文书
Mybatis是这样防止sql注入的
2021/12/06 Java/Android