二叉树的非递归(先序、中序、后序)遍历
来源:互联网 发布:破解无线网络密码软件 编辑:程序博客网 时间:2024/05/21 06:39
二叉树的特点是每个结点至多只有两棵子树,它是一种很重要的数据结构,从树的特点我们可以利用递归很容易的实现它的创建以及遍历操作,上一篇已经用递归的方法实现了二叉树的先序、中序和后序的遍历,下面的代码是二叉树的非递归遍历的实现,三种遍历方式都给出了两种实现方法(注释掉的即为第二种实现方法),注释部分已经讲原理写出来了,由于自己语言组织能力不是很好,原理就是从网上找来的,我自己是通过这些原理来实现的遍历二叉树,希望也能给看到代码的人同样帮助。
/**@2012-12-14*二叉树的非递归(先序、中序、后序)遍历*/#include<iostream>using namespace std;typedef char TElemType;//二叉树数据元素的类型typedef struct BitreeNode{TElemType TItem;struct BitreeNode *lchild;struct BitreeNode *rchild;}BitreeNode,*Bitree;typedef structSNode{ Bitree SItem;struct SNode *next;}SNode , * LinkStack;//初始化二叉树int InitBitree(Bitree &T){T=(Bitree)malloc(sizeof(BitreeNode));if(!T)return 0;T->TItem='#';T->lchild=NULL;T->rchild=NULL;return 1;}//初始化栈int InitStack(LinkStack &S){S=(LinkStack)malloc(sizeof(SNode)); //通过malloc函数分配空间if (!S)return 0; //如果分配失败,则返回0S->next=NULL;return 1;}//判断栈是否为空int StackEmpty(LinkStack S){if (S!=NULL) //判断栈是否存在{if (S->next==NULL){return 1;}}return 0;}//创建二叉树int CreateBitree(Bitree &T){TElemType ch;ch=getchar();//测试字符串abc##de#g##f###if(ch=='#')T=NULL;else{T=(Bitree)malloc(sizeof(BitreeNode));if(!T)return 0;else{T->TItem=ch;CreateBitree(T->lchild);CreateBitree(T->rchild);}}return 1;}//获取栈顶元素int GetTop(LinkStack S,Bitree &e){LinkStack q=S;if (S!=NULL) //判断栈是否存在{if (q->next!=NULL)//判断栈是否为空{while (q->next!=NULL){q=q->next;}e=q->SItem;return 1;}}return 0; //如果不能得到数据元素,则返回0(false)}//压栈函数int Push(LinkStack &S,Bitree e){LinkStack q=S;LinkStack m=(LinkStack)malloc(sizeof(SNode)); //通过malloc函数分配空间if (S!=NULL){while (q->next!=NULL){q=q->next;}m->SItem=e;m->next=NULL;q->next=m;}return 0;}//出栈函数int Pop(LinkStack &S,Bitree &e){LinkStack q=S;if (S!=NULL){if (q->next!=NULL) //若栈不是空的{while (q->next->next!=NULL){q=q->next;}e=q->next->SItem;q->next=NULL;return 1;}}return 0;}//遍历访问函数int Visit(TElemType e){if(e!=NULL){cout<<e<<" ";return 1;}elsereturn 0;}/*先序遍历二叉树根->左->右;1)访问结点P,并将结点P入栈;2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1); 若不为空,则将P的左孩子置为当前的结点P;3)直到P为NULL并且栈为空,则遍历结束。*/int PreOrederTraverse(Bitree &T,int(*Visit)(TElemType)){/*LinkStack S;Bitree p=T;InitStack(S);Push(S,T);while (p || !StackEmpty(S)){while (p!=NULL){Visit(p->TItem);Push(S,p);p=p->lchild;}if(!StackEmpty(S)){GetTop(S,p);Pop(S,p);p=p->rchild;}}*/LinkStack S;Bitree p=T;InitStack(S);Push(S,T);while (!StackEmpty(S)){while (GetTop(S,p) && p){if(!Visit(p->TItem))return 0;Push(S,p->lchild);//向左走到尽头}Pop(S,p);//空指针退栈if(!StackEmpty(S)){//访问节点,向右一步Pop(S,p);Push(S,p->rchild);}}return 0;}/**中遍历二叉树:左->根->右1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;3)直到P为NULL并且栈为空则遍历结束*/int InOrderTraverse(Bitree &T,int(*Visit)(TElemType)){/*LinkStack S;Bitree p=T;InitStack(S);Push(S,T);//根指针进栈while (p || !StackEmpty(S)){if(p){Push(S,p);p=p->lchild;//根指针进栈,遍历左子树}else//根指针退栈,访问根结点,遍历右子树{Pop(S,p);if(!Visit(p->TItem))return 0;p=p->rchild;}}*/LinkStack S;Bitree p=T;InitStack(S);Push(S,T);//根指针进栈while (!StackEmpty(S)){while (GetTop(S,p) && p){Push(S,p->lchild);//向左走到尽头}Pop(S,p);//空指针退栈if(!StackEmpty(S)){//访问节点,向右一步Pop(S,p);if(!Visit(p->TItem))return 0;Push(S,p->rchild);}}return 1;}/**后序遍历二叉树:左->右->根1)对于任一结点P,先将其入栈。2)如果P不存在左孩子和右孩子,或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则可以直接访问该结点。3)若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问。 左孩子和右孩子都在根结点前面被访问。*/int PostOrderTraverse(Bitree &T,int(*Visit)(TElemType)){/*Bitree q=T;LinkStack S;InitStack(S);while (T || !StackEmpty(S)){if (T){Push(S, T);T=T->lchild;}else{GetTop(S, T);if (T->rchild==NULL || T->rchild==q){Visit(T->TItem);Pop(S, T);q=T;T=NULL;}else{T=T->rchild;}} }*/LinkStack S;Bitree cur;//当前结点Bitree pre=NULL;//前一次访问的结点InitStack(S);Push(S,T);//根指针进栈 while(!StackEmpty(S)) { GetTop(S,cur); if((cur->lchild==NULL&&cur->rchild==NULL)||(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild))) {//如果当前结点没有孩子结点或者孩子节点都已被访问过 Visit(cur->TItem); Pop(S,cur); pre=cur; } else//将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问 { if(cur->rchild!=NULL) Push(S,cur->rchild); if(cur->lchild!=NULL) Push(S,cur->lchild); } } return 0;}int main(){Bitree T;InitBitree(T);CreateBitree(T);cout<<"先序遍历:";PreOrederTraverse(T,Visit);cout<<endl;cout<<"中序遍历:";InOrderTraverse(T,Visit);cout<<endl;cout<<"后序遍历:";PostOrderTraverse(T,Visit);cout<<endl;return 0;}
- 二叉树的先序/中序/后序(递归、非递归)+层序遍历
- 二叉树的先序、中序、后序遍历(递归 and 非递归)
- 二叉树的先序、中序、后序递归遍历和非递归遍历
- 二叉树的遍历(2)--先序遍历,中序遍历,后序遍历(非递归)
- 二叉树的非递归遍历(先序,中序,后序)
- 二叉树的非递归(先序、中序、后序)遍历
- 二叉树遍历的非递归算法(先序、中序、后序)代码实现
- 二叉树的先序、中序、后序遍历的递归和非递归实现
- 二叉树的后序,先序,中序遍历的非递归遍历
- 二叉树的先序、中序、后序、层序递归及非递归遍历
- 二叉树的遍历 中序 后序 先序 递归 非递归
- 二叉树的创建和先序,中序,后序,递归,非递归遍历
- 二叉树的遍历 先序 中序 后序 递归非递归
- 二叉树非递归和递归遍历(先序,中序,后序)
- 二叉树 非递归 先序遍历 中序遍历 后序遍历 层次遍历
- 二叉树的先序遍历、中序遍历以及后序遍历(递归以及非递归方式)
- 先序遍历中序遍历后序遍历确定一棵二叉树(递归、非递归)
- 二叉树的建树、遍历(先序、中序、后序、层次)(递归和非递归)--Java实现
- Thinking In Java
- android基于SlidingDrawer实现抽屉效果
- 常用图像处理算法(三)
- 关于fedora 17启动时显示cannot open font file true的解决办法
- 自写模态对话框时,ok和cancel的问题
- 二叉树的非递归(先序、中序、后序)遍历
- 面向接口编程还有一些好处:
- File类的用法总结,及文件过滤器的介绍。
- hdu 1422 最大子序列和问题的变形,最长非负子序列
- xml的应用
- 魔兽哈希算法封装和测试
- Django框架(一): 安装部署
- 技术人员创业后就不再适合继续编码了?
- MYSQL分页limit速度太慢