二叉树前序,中序以及后序的非递归算法实现(外加层序)
最近在学数据结构里面的二叉树,就把三个遍历的非递归算法以及层序遍历写了一下hhh
感觉就是用栈模拟了一下递归算法,其实三种遍历的方法大体相似,主要就是在访问节点值的时候对代码进行了部分改动
结构体类型
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
算法代码如下:
1.前序遍历:
每此访问子树的时候即可输出节点的值
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType))//Status 是int,Visit就是个输出函数hhhh
{
stack<BiTree> s;
BiTree p=T;
while(p||!s.empty())
{
if(p)
{
s.push(p);
Visit(p->data);//遇到根节点即可输出节点的值
p=p->lchild;//向左走到尽头
}
else
{
p=s.top();
s.pop();
p=p->rchild;//根节点退栈,访问右子树
}
}
return OK;
}
2.中序遍历:访问完根节点的左子树以后即可输出根节点的值
写了两种,一种是遇到空节点入栈以后再弹出的,一种是合法节点才入栈的
Status InOrderTraverse1(BiTree T,Status(*Visit)(TElemType))
{
stack<BiTree> s;
BiTree p=T;
while(p||!s.empty())
{
if(p)
{
s.push(p);
p=p->lchild;//向左走到头
}
else
{
p=s.top();
s.pop();
Visit(p->data);//访问根节点,此时已经遍历完了根节点的左子树
p=p->rchild;
}
}
return OK;
}
Status InOrderTraverse2(BiTree T,Status(*Visit)(TElemType))
{
stack<BiTree> s;
BiTree p;
s.push(T);
while(!s.empty())
{
while(!s.empty()&&s.top())
{
p=s.top();
s.push(p->lchild);
}
s.pop();
if(!s.empty())
{
p=s.top();
s.pop();
Visit(p->data);
s.push(p->rchild);
}
}
return OK;
}
3.后序遍历:稍微复杂一些,在遍历完左子树和右子树的时候才输出根节点的值,所以需要一个指针r,指向访问根节点前的指针位置,当且仅当根节点前一个节点是右节点或者右节点不存在的时候输出根节点的值,并且将根节点退栈,其它情况遍历根节点的右子树,并且根节点不退栈。
Status PostOrderTraverse(BiTree T,Status(*Visit)(TElemType))
{
stack<BiTree> s;
BiTree p,r;
p=T,r=NULL;
while(p||!s.empty())
{
if(p)
{
s.push(p);
p=p->lchild;//依旧是向左走到头
}
else
{
p=s.top();//p是根节点的指针值
if(!p->rchild||p->rchild==r)当且仅当根节点前一个节点是右节点或者右节点不存在的时候输出根节点的值
{
Visit(p->data);
s.pop();//根节点退栈
r=p;//r指向刚刚访问过的节点
p=NULL;//p节点的值已经访问过,为了避免重复访问,则令其为空
}
else p=p->rchild;//其它情况下访问根节点的右子树
}
}
return OK;
}
4.层序遍历:感觉是宽搜hhh 就是利用队列先进先出的特性得到待操作的子序列,每次对队头进行操作,访问队头的值并且添加队头元素的左节点和右节点到队列里面(如果队列左右节点存在的时候),一直操作到队列为空为止。
Status LevelTraverse(BiTree T,Status (*Visit)(TElemType))
{
queue <BiTree> q;
if(T)
{
q.push(T);//根节点进入队列
while(!q.empty())//一直循环到队列为空为止
{
BiTree T1;
T1=q.front();//令T1为队列的头元素
printf("%c",T1->data);//输出队列的头元素
q.pop();//头元素出队
if(T1->lchild!=NULL)
q.push(T1->lchild);
//如果头元素的左子树存在,则入队
if(T1->rchild!=NULL)
q.push(T1->rchild);
//如果头元素的右子树存在,则入队
}
}
return OK;
}