二叉树的非递归(先序、中序、后序)遍历

来源:互联网 发布:破解无线网络密码软件 编辑:程序博客网 时间: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;}


原创粉丝点击