在4.2章节做的扩展的基础上,采用非递归的方式实现了前序遍历、中序遍历和后序遍历1.二叉搜索树(本章以二叉搜索树为例)2.代码(在traversalByStack方法中实现了二叉树的非递归遍历)/***内容:二叉树二叉查找树的实现*auth:yujiaming*create:2020-10-25*/rootNode=null;$this->size=0;}/***二叉树的根节点*@varNode*/protected$rootNode;/***获取根节点*@returnNode*/publicfunctiongetRootNode():Node{return$this->rootNode;}/***二叉树的数量*@varint*/protected$size;/***获取二叉树的元素个数Number*@returnint*/publicfunctiongetSize():int{return$this->size;}/***判断是否为空*@returnbool*/publicfunctionisEmpty():bool{return$this->size==0;}/***插入节点*@parammixed$value*@returnvoid*/publicfunctionadd($value):void{//如果没有根节点,则插入根节点if(is_null($this->rootNode)){$this->rootNode=newNode($value);$this->尺寸;返回;}else{$this->addChild($value,$this->rootNode);返回;}}/***插入子节点*@parammixed$value*@paramNode|null$parentNode*/privatefunctionaddChild($value,?Node$parentNode):void{if(bccomp($parentNode->getValue(),$value)>0){//左子节点if(is_null($parentNode->getLeftChild())){$parentNode->setLeftChild(newNode($value));$这个->尺寸++;返回;}else{$this->addChild($value,$parentNode->getLeftChild());}}elseif(bccomp($parentNode->getValue(),$value)<0){//右子if(is_null($parentNode->getRightChild())){$parentNode->setRightChild(newNode($value));$这个->尺寸++;返回;}else{$this->addChild($value,$parentNode->getRightChild());}}else{返回;}}constTRAVERSAL_PREORDER=1;//先序遍历constTRAVERSAL_INORDER=2;//中序遍历constTRAVERSAL_POSTORDER=3;//后序遍历/***遍历二叉树*@paramint$traversalType*@returnstring*/publicfunctiontraversal(int$traversalType=1):string{$result='';switch($traversalType){caseself::TRAVERSAL_PREORDER:$this->preorderTraversal($result,$this->rootNode);}休息;案例self::TRAVERSAL_INORDER:$this->inorderTraversal($result,$this->rootNode);休息;案例self::TRAVERSAL_POSTORDER:$this->postorderTraversal($result,$this->rootNode);休息;默认值:中断;}返回$结果;}/***前序遍历*@paramstring$result结果值*@paramNode|null$nodeNode*@returnvoid*/protectedfunctionpreorderTraversal(string&$result,?Node$node):void{if(is_null($node))返回;//拼接if($result!='')$result.='->';//先遍历当前节点$result.=$node->getValue();//然后遍历左孩子$this->preorderTraversal($result,$node->getLeftChild());//}/***中序遍历*@paramstring$result结果值*@paramNode|null$nodenode*@returnvoid*/publicfunctioninorderTraversal(string&$result,?Node$node):void{if(is_null($node))返回;//先遍历左儿子$this->inorderTraversal($result,$node->getLeftChild());//拼接if($result!='')$result.='->';//再次获取当前节点$result.=$node->getValue();//遍历右孩子$this->inorderTraversal($result,$node->getRightChild());返回;}/***后序遍历*@paramstring$result结果值*@paramNode|null$nodenode*@returnvoid*/publicfunctionpostorderTraversal(string&$result,?Node$node):void{if(is_null($node))返回;//先遍历左儿子$this->postorderTraversal($result,$node->getLeftChild());//遍历右孩子$this->postorderTraversal($result,$node->getRightChild());//拼接if($result!='')$result.='->';//获取当前节点$result.=$node->getValue();返回;}/***非递归遍历*@paramint$traversalType*@returnstring*/publicfunctiontraversalByStack(int$traversalT类型=1):字符串{$stack=newBaseStack(newBaseArray());$结果='';switch($traversalType){//先序遍历caseself::TRAVERSAL_PREORDER://将根节点插入栈底$stack->push($this->rootNode);//循环while(!$stack->isEmpty()){//弹出栈顶节点//循环后会先弹出左子再弹出右子,中间节点的值并在最后一个循环中输出$node=$stack->pop();//将栈顶元素拼接成结果集if($result!=''){$result.='->';}$result.=$node->getValue();//从栈顶插入右孩子入栈if(!is_null($node->getRightChild())){$stack->push($node->getRightChild());}//将从栈顶弹出的左孩子插入栈中if(!is_null($node->getLeftChild())){$stack->push($node->getLeftChild());}}休息;//中序遍历案例self::TRAVERSAL_INORDER://将根节点赋给节点变量$node=$this->rootNode;//循环//!$stack->isEmpty()>>用于判断栈中的元素是否全部弹出//!is_null($node)>>用于判断左子节点是否已经遍历while(!$stack->isEmpty()||!is_null($node)){//遍历节点,将节点的所有左子节点一一插入栈中while(!is_null($node)){$stack->push($node);//echo'插入节点:'。$node->getValue().PHP_EOL;$node=$node->getLeftChild();}//弹出栈顶的第一个元素,左孩子或者是根节点$popNode=$stack->pop();如果($result!=''){$result.='->';}//输出结果$result.=$popNode->getValue();//将右孩子赋给节点节点变量$node=$popNode->getRightChild();}返回$结果;休息;//后序遍历caseself::TRAVERSAL_POSTORDER://创建一个临时栈$stackTmp=newBaseStack(newBaseArray());//将根节点放入栈底$stackTmp->push($this->rootNode);//循环临时堆栈while(!$stackTmp->isEmpty()){//从临时堆栈顶部弹出一个元素$node=$stackTmp->pop();//将元素的左子节点放入临时栈if(!is_null($node->getLeftChild())){$stackTmp->push($node->getLeftChild());}//将元素的右孩子放入临时栈if(!is_null($node->getRightChild())){$stackTmp->push($node->getRi正确的孩子());}//将节点放入需要遍历数据的栈$stack->push($node);}while(!$stack->isEmpty()){if($result!=''){$result.='->';}$result.=$stack->pop()->getValue();}休息;默认值:中断;}返回$结果;}}3。前序遍历代码Block//将根节点插入栈底$stack->push($this->rootNode);//循环while(!$stack->isEmpty()){//弹出节点栈顶//循环后先弹出左儿子,再弹出右儿子。中间节点的值将在最后一个循环中输出。$node=$stack->pop();//输出栈顶元素echo$node->getValue();//从栈顶插入右孩子入栈if(!is_null($node->getRightChild())){$stack->push($node->getRightChild());}//将弹出栈顶的左孩子插入栈中if(!is_null($node->getLeftChild())){$stack->push($node->getLeftChild());}}代码流分析4.中序遍历代码块//将根节点赋值给节点变量$node=$this->rootNode;//循环//!$stack->isEmpty()>>用于判断栈中所有元素是否弹出//!is_null($node)>>用于判断是否遍历左子节点while(!$stack->isEmpty()||!is_null($node)){//循环节点,将节点的所有左子节点一个一个插入栈中while(!is_null($node)){$stack->推($节点);$node=$node->getLeftChild();}//弹出栈顶的第一个元素,左子节点或根节点$popNode=$stack->pop();//输出结果echo$popNode->getValue();//将右孩子分配给节点变量$node=$popNode->getRightChild();}code流程分析5.后序遍历代码块//创建临时栈$stackTmp=newBaseStack(newBaseArray());//将根节点放入栈底$stackTmp->push($this->rootNode);//循环临时堆栈while(!$stackTmp->isEmpty()){//从临时堆栈顶部弹出一个元素$node=$stackTmp->pop();//将元素的左孩子放入临时堆栈if(!is_null($node->getLeftChild())){$stackTmp->push($node->getLeftChild());}//将元素的右孩子放入临时栈if(!is_null($node->getRightChild())){$stackTmp->push($node->getRightC希尔德());}//将节点放入需要遍历数据的栈中$stack->push($node);}while(!$stack->isEmpty()){echo$stack->pop()->getValue();}代码流分析
