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获取文件绝对路径的代码(上一级目录)
May 29 PHP
php中邮箱地址正则表达式实现与详解
Apr 24 PHP
PHP时间戳与日期之间转换的实例介绍
Apr 19 PHP
用PHP解决的一个栈的面试题
Jul 02 PHP
Thinkphp的volist标签嵌套循环使用教程
Jul 08 PHP
PHP中echo,print_r与var_dump区别分析
Sep 29 PHP
PHP中使用OpenSSL生成证书及加密解密
Feb 05 PHP
php PDO实现的事务回滚示例
Mar 23 PHP
PHP使用Redis长连接的方法详解
Feb 12 PHP
PHP7基于curl实现的上传图片功能
May 11 PHP
laravel csrf排除路由,禁止,关闭指定路由的例子
Oct 21 PHP
禁止直接访问php文件代码分享
May 05 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
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
2009/06/08 PHP
PHP数据类型之布尔型的介绍
2013/04/28 PHP
php中删除、清空session的方式总结
2015/10/09 PHP
PHP内存使用情况如何获取
2015/10/10 PHP
PHP实现Session入库/存入redis的方法
2017/05/04 PHP
PHP实践教程之过滤、验证、转义与密码详解
2017/07/24 PHP
Javascript中eval函数的使用方法与示例
2007/04/09 Javascript
javascript下判断一个元素是否存在的代码
2010/03/05 Javascript
ExtJs使用IFrame的实现代码
2010/03/24 Javascript
容易被忽略的JS脚本特性
2011/09/13 Javascript
2014 年最热门的21款JavaScript框架推荐
2014/12/25 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
AngularJS Module方法详解
2015/12/08 Javascript
javascript数据类型验证方法
2015/12/31 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
Angular动态添加、删除输入框并计算值实例代码
2017/03/29 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
2017/04/14 jQuery
微信小程序表单验证功能完整实例
2017/12/01 Javascript
Vue-router编程式导航的两种实现代码
2021/03/04 Vue.js
Python对列表排序的方法实例分析
2015/05/16 Python
django初始化数据库的实例
2018/05/27 Python
将pip源更换到国内镜像的详细步骤
2019/04/07 Python
python 读取修改pcap包的例子
2019/07/23 Python
Django实现图片上传功能步骤解析
2020/04/22 Python
六种酷炫Python运行进度条效果的实现代码
2020/07/17 Python
Python爬取股票信息,并可视化数据的示例
2020/09/26 Python
利用Python批量识别电子账单数据的方法
2021/02/08 Python
canvas里面如何基于随机点绘制一个多边形的方法
2018/06/13 HTML / CSS
美国隐形眼镜网上商店:Lens.com
2019/09/03 全球购物
财务会计专业毕业生自荐信
2013/10/19 职场文书
高中生操行评语
2014/04/25 职场文书
小摄影师教学反思
2014/04/27 职场文书
巴黎圣母院读书笔记
2015/06/26 职场文书
员工试用期工作总结
2019/06/20 职场文书
Python趣味挑战之实现简易版音乐播放器
2021/05/28 Python
GO中sync包自由控制并发示例详解
2022/08/05 Golang