二叉树的创建与前序、中序和后序的递归与非递归调用
来源:互联网 发布:软件删不掉怎么办 编辑:程序博客网 时间:2024/06/06 02:12
#include<iostream>#include<string>#include<vector>#include<stack>using namespace std;typedef char ElemType;class BiTNode{friend class BiTree;private:ElemType data;BiTNode *lchild,*rchild; //左右孩子指针};class BiTree:public BiTNode{public:void InputBiTNode();//输入构成数的结点元素,‘#’表示空串void Pre_CreateBiTree(BiTNode *&T);//先序构造二叉树void visit(ElemType e);//visit函数用于输出结点元素void PreOrderTraverse(BiTNode *T);//先序遍历二叉树T(递归方式)void InOrderTraverse(BiTNode *T);//中序遍历二叉树T(递归方式)void PostOrderTraverse(BiTNode *T);//后序遍历二叉树T(递归方式)void Iterator_PreOrderTraverse(BiTNode *T);//先序遍历二叉树T(非递归方式)void Iterator_InOrderTraverse(BiTNode *T);//中序遍历二叉树T(非方递归式)void Iterator_PostOrderTraverse(BiTNode *T);//后序遍历二叉树T(非递归方式)void Iterator_PreOrderTraverse2(BiTNode *T);//先序遍历二叉树T(非递归方式2)void Iterator_InOrderTraverse2(BiTNode *T);//中序遍历二叉树T(非方递归式2)void Iterator_PostOrderTraverse2(BiTNode *T);//后序遍历二叉树T(非递归方式2)private:vector<ElemType> elem;};void BiTree::InputBiTNode(){ElemType ch;cout<<"!!!注意:(1)'#'表示空结点;(2)请在输入的字符串末尾加0,作为输入结束的标志。"<<endl;while(cin>>ch&&ch!='0'){elem.push_back(ch);//在容器中加入结点元素}//while}//InputBiBodevoid BiTree::Pre_CreateBiTree(BiTNode *&T){ vector<ElemType>::iterator it=elem.begin();//迭代器it指向elem的开头if(it!=elem.end()){if(*it=='#')//字符为空格,表示结点不存在{T=NULL;elem.erase(it);//删除迭代器it指向的elem中的元素,作用是依次删除elem的第一个元素}//ifelse{if(!(T=new BiTNode))exit(-1);T->data=*it;//生成根结点elem.erase(it);//删除迭代器it指向的elem中的元素,作用是依次删除elem的第一个元素Pre_CreateBiTree(T->lchild); //构造左子树Pre_CreateBiTree(T->rchild);//构造右子树}//else}//ifelse//此时elem为空,使此时T=NULL;,即结束最初的T的结点的赋值T=NULL;}//Pre_CreateBiTreevoid BiTree::PreOrderTraverse(BiTNode *T){if(T)//二叉树存在{visit(T->data);//访问根结点PreOrderTraverse(T->lchild);//先序遍历左子树PreOrderTraverse(T->rchild);//先序遍历右子树}//if}//PreOrderTraversevoid BiTree::InOrderTraverse(BiTNode *T){if(T){InOrderTraverse(T->lchild);//中序遍历左子树visit(T->data);//访问根结点InOrderTraverse(T->rchild);//中序遍历右子树}//if}//InOrderTraversevoid BiTree::PostOrderTraverse(BiTNode *T){if(T){PostOrderTraverse(T->lchild);//后序遍历左子树PostOrderTraverse(T->rchild);//后序遍历右子树visit(T->data);//访问根结点}//if}//PostOrderTraversevoid BiTree::Iterator_PreOrderTraverse(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q;S.push(T);//根指针入栈while(!S.empty()){while((q=S.top())&&q)//先访问结点,再将结点的左子树入栈,栈顶为空指针结束{visit(q->data);S.push(q->lchild);}//whileS.pop();//空指针出栈if(!S.empty())//由于结点元素已被访问,因此此处只需删除结点,将结点的右结点入栈{q=S.top();S.pop();//访问结点时将其从栈中删除S.push(q->rchild);}//if}//while}//Iterator_PreOrderTraversevoid BiTree::Iterator_InOrderTraverse(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q;S.push(T);//根指针入栈while(!S.empty()){while((q=S.top())&&q)//向左走到尽头{S.push(q->lchild);}//whileS.pop();//空指针出栈if(!S.empty())//访问结点,将结点的右结点入栈{q=S.top();S.pop();//访问结点时将其从栈中删除visit(q->data);S.push(q->rchild);//将右结点入栈}//if}//while}//Iterator_InOrderTraversevoid BiTree::Iterator_PostOrderTraverse(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q,*point=T;S.push(T);//根指针入栈while(!S.empty()){while((q=S.top())&&q)//向左走到尽头{S.push(q->lchild);}//whileS.pop();//空指针出栈if(!S.empty()){q=S.top();S.push(q->rchild);//右结点入栈if(S.top()==NULL)//入栈的右结点为空{S.pop();//空指针出栈point=S.top();S.pop();//访问根结点并出栈visit(point->data);while((!S.empty())&&(S.top()->rchild==point))//栈顶结点的右结点是刚被访问的结点{point=S.top();S.pop();//由于该结点的右结点已经被访问,说明完成了左右子树的遍历visit(point->data);//该结点作为子树的根结点则被出栈访问 }//whileif(!S.empty()){q=S.top();//此时栈顶结点的右结点还未入栈S.push(q->rchild);//右结点入栈}//if}//if}//if}//while}//Iterator_PostOrderTraversevoid BiTree::Iterator_PreOrderTraverse2(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q=T;while(q||(!S.empty())){if(q){visit(q->data);//访问根结点S.push(q);q=q->lchild;//遍历左子树}//ifelse{q=S.top();S.pop();//采用先序遍历,结点入栈时已被访问,因此出栈时无需访问q=q->rchild;}//else}//while}//Iterator_PreOrderTraverse2void BiTree::Iterator_InOrderTraverse2(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q=T;while(q||(!S.empty())){if(q)//结点存在{S.push(q);//根指针进栈,遍历左子树,q=q->lchild;}//ifelse//根指针退栈,访问根结点{q=S.top();S.pop();visit(q->data);q=q->rchild;//遍历右子树}//else}//while}//Iterator_InOrderTraverse2void BiTree::Iterator_PostOrderTraverse2(BiTNode *T){stack<BiTNode*> S;//用来存储树结点的BiTNode *q=T,*point=T;while(q||(!S.empty())){if(q){S.push(q);//根指针进栈,遍历左子树q=q->lchild;}//ifelse{q=S.top();q=q->rchild;//遍历右子树if(!q)//将要入栈的右子树为空{point=S.top();S.pop();//在遍历完左右子树后访问根结点visit(point->data);while((!S.empty())&&(S.top()->rchild==point))//栈顶结点的右结点是刚被访问的结点{point=S.top();S.pop();//由于该结点的右结点已经被访问,说明完成了左右子树的遍历visit(point->data);//该结点作为子树的根结点则被出栈访问 }//whileif(!S.empty()){q=S.top();//此时栈顶结点的右结点还未入栈q=q->rchild;//右结点入栈}//if}//if}//else}//while}//Iterator_PostOrderTraverse2void BiTree::visit(ElemType e){cout<<e;}//visitvoid main(){BiTree BT;BiTNode *T;BT.InputBiTNode();BT.Pre_CreateBiTree(T);cout<<"\n"<<"先序遍历(递归)二叉树T:"<<endl;BT.PreOrderTraverse(T);cout<<endl;cout<<"先序遍历(非递归)二叉树T:"<<endl;BT.Iterator_PreOrderTraverse(T);cout<<endl;cout<<"先序遍历(非递归2)二叉树T:"<<endl;BT.Iterator_PreOrderTraverse2(T);cout<<endl;cout<<"\n"<<"中序遍历(递归)二叉树T:"<<endl;BT.InOrderTraverse(T);cout<<endl;cout<<"中序遍历(非递归)二叉树T:"<<endl;BT.Iterator_InOrderTraverse(T);cout<<endl;cout<<"中序遍历(非递归2)二叉树T:"<<endl;BT.Iterator_InOrderTraverse2(T);cout<<endl;cout<<"\n"<<"后序遍历(递归)二叉树T:"<<endl;BT.PostOrderTraverse(T);cout<<endl;cout<<"后序遍历(非递归)二叉树T:"<<endl;BT.Iterator_PostOrderTraverse(T);cout<<endl;cout<<"后序遍历(非递归2)二叉树T:"<<endl;BT.Iterator_PostOrderTraverse2(T);cout<<endl;}//main
以下图所示二叉树为例,对中序(非递归)和后序(非递归2)算法栈的入栈和出栈情况进行简单说明:
0 0
- 二叉树的创建与前序、中序和后序的递归与非递归调用
- 【二叉树】 前序、中序和后序的递归遍历与非递归遍历
- 二叉树的中序、后序、前序的递归与非递归输出
- 二叉树的前序,中序,后序的递归与非递归遍历
- 二叉树的前序、中序、后序遍历(递归与非递归)
- 二叉树的递归与非递归遍历(前序、中序、后序)
- 二叉树的递归与非递归遍历(前序、中序、后序)
- 二叉树的递归与非递归遍历(前序、中序、后序)
- 二叉树的递归与非递归遍历(前序、中序、后序)
- 【二叉树遍历算法】——前/中/后序递归与非递归的实现
- 【数据结构】二叉树(前、中、后)序遍历的递归与非递归算法
- JAVA实现二叉树的前、中、后序遍历(递归与非递归)
- 二叉树的深度优先dfs遍历(前序、中序和后序;递归与非递归)
- 二叉树的创建,遍历(前序,中序,后序)-递归 非递归
- java语言实现二叉树的前序、中序与后序遍历(递归与非递归)
- java语言实现二叉树的前序、中序与后序遍历(递归与非递归) 层次遍历
- 二叉树的前序、中序、后序的实现(递归和非递归)
- 二叉树的前序,中序,后序的递归与非递归遍历以及按层遍历
- php类变量赋值问题
- linux中用date命令获取昨天、明天或多天前后的日期
- JAVA 取汉字拼音首字母
- oracle中if/else功能的实现的3种写法
- Android UE/UI相关
- 二叉树的创建与前序、中序和后序的递归与非递归调用
- 惹毛程序员的十件事!需求变更居然不是第一!
- LeedCode:Sort List
- 单词缩写
- Git版本控制软件结合GitHub从入门到精通常用命令学习手册
- 【c++】注册OCX控件
- MKNetworkKit: 网络处理又一利器
- jQuery 中的事件参数传递机制
- LINQ to SQLite完美解决方案