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中的时间处理
Oct 09 PHP
用PHP和ACCESS写聊天室(八)
Oct 09 PHP
发布一个用PHP fsockopen写的HTTP下载的类
Feb 22 PHP
php 正确解码javascript中通过escape编码后的字符
Jan 28 PHP
php include加载文件两种方式效率比较
Aug 08 PHP
php编写一个简单的路由类
Apr 13 PHP
php实现文件下载实例分享
Jun 02 PHP
Codeigniter实现处理用户登录验证后的URL跳转
Jun 12 PHP
PHP中可以自动分割查询字符的Parse_str函数使用示例
Jul 25 PHP
PHP实现把文本中的URL转换为链接的auolink()函数分享
Jul 29 PHP
thinkPHP5框架闭包函数与子查询传参用法示例
Aug 02 PHP
Laravel 实现在Blade模版中使用全局变量代替路径的例子
Oct 22 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
163的邮件用phpmailer发送(实例详解)
2013/06/24 PHP
用PHP写的一个冒泡排序法的函数简单实例
2016/05/26 PHP
PHP解析url并得到url参数方法总结
2018/10/11 PHP
PHP数组遍历的几种常见方式总结
2019/02/15 PHP
JavaScript 函数replace深入了解
2013/03/14 Javascript
深入了解javascript中的prototype与继承
2013/04/14 Javascript
浅谈javascript的Array.prototype.slice.call
2015/08/31 Javascript
JavaScript如何禁止Backspace键
2015/12/02 Javascript
jQuery 利用$.ajax 时获取原生XMLHttpRequest 对象的方法
2016/08/25 Javascript
微信小程序 地图定位简单实例
2016/10/14 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
利用node.js写一个爬取知乎妹纸图的小爬虫
2017/05/03 Javascript
ReactNative页面跳转Navigator实现的示例代码
2017/08/02 Javascript
详解Node.js一行命令上传本地文件到服务器
2019/04/22 Javascript
20多个小事例带你重温ES10新特性(小结)
2019/09/29 Javascript
springboot+vue实现文件上传下载
2020/11/17 Vue.js
多种类型jQuery网页验证码插件代码实例
2021/01/09 jQuery
[01:32]DOTA2上海特锦赛现场采访:最想COS的英雄
2016/03/25 DOTA
在Python程序中操作文件之isatty()方法的使用教程
2015/05/24 Python
python pip源配置,pip配置文件存放位置的方法
2019/07/12 Python
python 并发编程 多路复用IO模型详解
2019/08/20 Python
python画环形图的方法
2020/03/25 Python
详解python中groupby函数通俗易懂
2020/05/14 Python
python如何快速拼接字符串
2020/10/28 Python
小程序canvas中文字设置居中锚点
2019/04/16 HTML / CSS
英国剑桥包官网:The Cambridge Satchel Company
2016/08/01 全球购物
Armor Lux法国官方网站:水手服装、成衣和内衣
2020/05/26 全球购物
Linux如何压缩可执行文件
2014/03/27 面试题
幼师自我鉴定
2014/02/01 职场文书
2016年教师党员承诺书范文
2016/03/24 职场文书
nginx处理http请求实现过程解析
2021/03/31 Servers
浅谈Python基础之列表那些事儿
2021/05/11 Python
canvas绘制折线路径动画实现
2021/05/12 Javascript
Django模型层实现多表关系创建和多表操作
2021/07/21 Python
一起来看看Vue的核心原理剖析
2022/03/24 Vue.js
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript