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 相关文章推荐
基于mysql的论坛(1)
Oct 09 PHP
php学习之 数组声明
Jun 09 PHP
通过5个php实例细致说明传值与传引用的区别
Aug 08 PHP
php操作mysqli(示例代码)
Oct 28 PHP
php支付宝接口用法分析
Jan 04 PHP
php微信开发之带参数二维码的使用
Aug 03 PHP
PHP制作登录异常ip检测功能的实例代码
Nov 16 PHP
php插入含有特殊符号数据的处理方法
Nov 24 PHP
phpstudy默认不支持64位php的解决方法
Feb 20 PHP
PHP 实现字符串翻转(包含中文汉字)的实现代码
Apr 01 PHP
PHP连接sftp并下载文件的方法教程
Aug 26 PHP
ThinkPHP5.0框架使用build 自动生成模块操作示例
Apr 11 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
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
PHP和JavaScrip分别获取关联数组的键值示例代码
2013/09/16 PHP
Linux下PHP加速器APC的安装与配置笔记
2014/10/24 PHP
php访问数组最后一个元素的函数end()用法
2015/03/18 PHP
为你总结一些php系统类函数
2015/10/21 PHP
JavaScript中的prototype.bind()方法介绍
2014/04/04 Javascript
基于zepto的移动端轻量级日期插件--date_picker
2016/03/04 Javascript
极力推荐10个短小实用的JavaScript代码段
2016/08/03 Javascript
Javascript创建类和对象详解
2017/05/31 Javascript
react-native动态切换tab组件的方法
2018/07/07 Javascript
详解angular2如何手动点击特定元素上的点击事件
2018/10/16 Javascript
详解webpack打包第三方类库的正确姿势
2018/10/20 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
Vue实现远程获取路由与页面刷新导致404错误的解决
2019/01/31 Javascript
微信小程序textarea层级过高的解决方法
2019/03/04 Javascript
Vue实现随机验证码功能
2020/12/29 Vue.js
[33:09]完美世界DOTA2联赛循环赛 Forest vs DM BO2第二场 10.29
2020/10/29 DOTA
Web服务器框架 Tornado简介
2014/07/16 Python
web.py获取上传文件名的正确方法
2014/08/26 Python
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
2016/01/20 Python
使用Python的Django框架结合jQuery实现AJAX购物车页面
2016/04/11 Python
Python清空文件并替换内容的实例
2018/10/22 Python
利用python实现在微信群刷屏的方法
2019/02/21 Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
2019/06/17 Python
在PyCharm的 Terminal(终端)切换Python版本的方法
2019/08/02 Python
PyQt+socket实现远程操作服务器的方法示例
2019/08/22 Python
python文字转语音的实例代码分析
2019/11/12 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
recorder.js 基于Html5录音功能的实现
2020/05/26 HTML / CSS
乡文化站暑期培训方案
2014/08/28 职场文书
乡镇防汛工作汇报
2014/10/28 职场文书
面试感谢信范文
2015/01/22 职场文书
2015年公务员试用期工作总结
2015/05/28 职场文书
总结一些Java常用的加密算法
2021/06/11 Java/Android
Python中异常处理用法
2021/11/27 Python
Mysql数据库group by原理详解
2022/07/07 MySQL