问题:非递归实现二叉树的遍历
非递归实现二叉树的先序遍历思路:先序遍历的思想是根左右,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,并访问,当为空时转入最左节点的右子树,再重复上述过程直到栈和树均为空。
非递归实现二叉树的中序遍历思路:先序遍历的思想是左根右,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,当为空时转入最左节点的右子树,并访问,再重复上述过程直到栈和树均为空。
非递归实现二叉树的后序遍历思路:先序遍历的思想是左右根,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,当为空时转入最左节点的右子树,如果右子树节点为空或被访问过,则访问,并记录当前节点为已访问节点,再重复上述过程直到栈和树均为空。
非递归实现二叉树的层次遍历思路:先申请一个队列,将根节点放到队列中,当此队列不为空时,访问头部节点,若此节点左孩子不为空,则将左孩子压入栈,若此节点右孩子不为空,则将右孩子压入栈,直到队列为空为止。
程序实现:
#include <iostream>
#include<stack>
#include<queue>
using namespace std;
typedef struct Btree
{
int num;
struct Btree * lchild;
struct Btree * rchild;
} *PBtree,Btree;
//建立一棵排序二叉树
PBtree createtree(PBtree root,int val)
{
PBtree newNode=new Btree();
newNode->lchild=NULL;
newNode->rchild=NULL;
newNode->num=val;
if(root==NULL)
{
root=newNode;
return newNode;
}
while(root!=NULL)
{
PBtree pback=NULL;
PBtree pcur=root;
while(pcur!=NULL)
{
pback=pcur;
if(pcur->num<val)
pcur=pcur->rchild;
else if(pcur->num>val)
pcur=pcur->lchild;
else
{
delete newNode;
return pcur;
}
}
if(pback->num>val)
pback->lchild=newNode;
else
pback->rchild=newNode;
return pback;
}
}
//递归实现先序遍历
void preorder(PBtree root)
{
if(root==NULL)
return ;
cout<<root->num<<" ";
preorder(root->lchild);
preorder(root->rchild);
}
//递归实现中序遍历
void inorder(PBtree root)
{
if(root==NULL)
return ;
inorder(root->lchild);
cout<<root->num<<" ";
inorder(root->rchild);
}
//递归实现后序遍历
void postorder(PBtree root)
{
if(root==NULL)
return ;
postorder(root->lchild);
postorder(root->rchild);
cout<<root->num<<" ";
}
//非递归实现先序遍历
void preorder_stack(PBtree root)
{
if(root==NULL)
return ;
stack<PBtree> s;
PBtree pb=root;
while(!s.empty()||pb)
{
//先遍历左子树节点
while(pb)
{
cout<<pb->num<<" ";
s.push(pb);
pb=pb->lchild;
}
//到最左的一个节点,看看它有没有右子树,若有,继续寻找该右子树的左节点
if(!s.empty())
{
pb=s.top();
s.pop();
pb=pb->rchild;
}
}
}
//递归实现中序遍历
void inorder_stack(PBtree root)
{
if(root==NULL)
return ;
stack<PBtree> s;
PBtree pb=root;
while(pb||!s.empty())
{
//先一直向左节点方向走
while(pb)
{
s.push(pb);
pb=pb->lchild;
}
//若为最左的那个节点输出
if(!s.empty())
{
pb=s.top();
s.pop();
cout<<pb->num<<" ";
pb=pb->rchild;
}
}
}
//递归实现后序遍历
void postorder_stack(PBtree root)
{
if(root==NULL)
return ;
stack<PBtree> s;
PBtree pb=root;
PBtree r;
while(!s.empty()||pb)
{
//走到最左边
if(pb)
{
s.push(pb);
pb=pb->lchild;
}
else
{
pb=s.top(); //向右
//判断其是否含有右子树,若有,则将右子树压入栈中,
//若无,则输出,且记录该节点为已经访问过的节点
if(pb->rchild&&pb->rchild!=r)//右子树存在且未被访问过
{
pb=pb->rchild; //转向右
s.push(pb); //压入栈
pb=pb->lchild; //再向左
}
else
{
pb=s.top(); //弹出再访问
s.pop();
cout<<pb->num<<" ";
r=pb; //标记已经被访问过的节点
pb=NULL; //重置指针p
}
}
}
}
//层次遍历,队列实现
void levelOrder(PBtree root)
{
if(root==NULL)
return;
queue<PBtree> q;
PBtree pb=root;
q.push(pb);
while(!q.empty())
{
pb=q.front();
q.pop();
cout<<pb->num<<" ";
if(pb->lchild)
q.push(pb->lchild);
if(pb->rchild)
q.push(pb->rchild);
}
}
int main()
{
PBtree root=NULL;
root=createtree(root,6);
int a[]={1,2,6,3,4,7,8,9,10,5};
for(int i=0;i<10;i++)
createtree(root,a[i]);
//递归方法实现各种遍历
cout<<"递归实现"<<endl;
cout<<"先序遍历:"<<endl;
preorder(root);
cout<<endl;
cout<<"中序遍历:"<<endl;
inorder(root);
cout<<endl;
cout<<"后序遍历:"<<endl;
postorder(root);
cout<<endl;
cout<<"***************************"<<endl;
cout<<"非递归实现"<<endl;
cout<<"先序遍历:"<<endl;
preorder_stack(root);
cout<<endl;
cout<<"中序遍历:"<<endl;
inorder_stack(root);
cout<<endl;
cout<<"后序遍历:"<<endl;
postorder_stack(root);
cout<<endl;
cout<<"层次遍历:"<<endl;
levelOrder(root);
cout<<endl;
return 0;
}
输出结果:
递归实现
先序遍历:
6 1 2 3 4 5 7 8 9 10
中序遍历:
1 2 3 4 5 6 7 8 9 10
后序遍历:
5 4 3 2 1 10 9 8 7 6
***************************
非递归实现
先序遍历:
6 1 2 3 4 5 7 8 9 10
中序遍历:
1 2 3 4 5 6 7 8 9 10
后序遍历:
5 4 3 2 1 10 9 8 7 6
层次遍历:
6 1 7 2 8 3 9 4 10 5