二叉树的特点是每个结点至多只有两棵子树,它是一种很重要的数据结构,从树的特点我们可以利用递归很容易的实现它的创建以及遍历操作,上一篇已经用递归的方法实现了二叉树的先序、中序和后序的遍历,下面的代码是二叉树的非递归遍历的实现,三种遍历方式都给出了两种实现方法(注释掉的即为第二种实现方法),注释部分已经讲原理写出来了,由于自己语言组织能力不是很好,原理就是从网上找来的,我自己是通过这些原理来实现的遍历二叉树,希望也能给看到代码的人同样帮助。
/* *@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 struct SNode { 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; //如果分配失败,则返回0 S->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; }else return 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; }