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版(2)
Oct 09 PHP
聊天室php&amp;mysql(六)
Oct 09 PHP
php常用表单验证类用法实例
Jun 18 PHP
浅谈使用PHP开发微信支付的流程
Oct 04 PHP
PHP调试的强悍利器之PHPDBG
Feb 22 PHP
ThinkPHP的常用配置选项汇总
Mar 24 PHP
php文件系统处理方法小结
May 23 PHP
php通过文件头判断格式的方法
May 28 PHP
PHP+iframe图片上传实现即时刷新效果
Nov 18 PHP
详谈PHP中public,private,protected,abstract等关键字的用法
Dec 31 PHP
Laravel框架使用Redis的方法详解
May 30 PHP
Thinkphp5.0 框架视图view的比较标签用法分析
Oct 12 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获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
PHP小偷程序的设计与实现方法详解
2016/10/15 PHP
基于jquery的一个OutlookBar类,动态创建导航条
2010/11/19 Javascript
原生javascript获取元素样式属性值的方法
2010/12/25 Javascript
JS实现Enter键跳转及控件获得焦点
2013/08/12 Javascript
分享js粘帖屏幕截图到web页面插件screenshot-paste
2020/08/21 Javascript
jquery实现拖动效果
2016/08/10 Javascript
自己封装的一个原生JS拖动方法(推荐)
2016/11/22 Javascript
jQuery监听浏览器窗口大小的变化实例
2017/02/07 Javascript
BACKBONE.JS 简单入门范例
2017/10/17 Javascript
bootstrap与pagehelper实现分页效果
2018/12/29 Javascript
详解Vue-Router源码分析路由实现原理
2019/05/15 Javascript
JavaScript之数组扁平化详解
2019/06/03 Javascript
微信小程序学习总结(四)事件与冒泡实例分析
2020/06/04 Javascript
vue2和vue3的v-if与v-for优先级对比学习
2020/10/10 Javascript
微信小程序实现简单购物车功能
2020/12/30 Javascript
[04:47]DOTA2-潍坊风行电子俱乐部探秘
2014/08/08 DOTA
对dataframe数据之间求补集的实例详解
2019/01/30 Python
django模板结构优化的方法
2019/02/28 Python
django基于restframework的CBV封装详解
2019/08/08 Python
Python的条件锁与事件共享详解
2019/09/12 Python
python 串口读取+存储+输出处理实例
2019/12/26 Python
解决Tensorboard 不显示计算图graph的问题
2020/02/15 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
Python 开发工具通过 agent 代理使用的方法
2020/09/27 Python
全球烹饪课程的领先预订平台:Cookly
2020/01/28 全球购物
大客户销售经理职责
2013/12/04 职场文书
打架检讨书100字
2014/01/19 职场文书
大学生优秀班干部事迹材料
2014/05/26 职场文书
国际会计专业求职信
2014/08/04 职场文书
史上最牛辞职信
2015/05/13 职场文书
交通事故起诉书
2015/05/19 职场文书
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
2021/05/05 Golang
口袋妖怪冰系十大最强精灵,几何雪花排第七,第六类似北极熊
2022/03/18 日漫
Docker安装MySql8并远程访问的实现
2022/07/07 Servers