非递归实现二叉树的遍历-二叉排序树的建立

问题:非递归实现二叉树的遍历

非递归实现二叉树的先序遍历思路:先序遍历的思想是根左右,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,并访问,当为空时转入最左节点的右子树,再重复上述过程直到栈和树均为空。

非递归实现二叉树的中序遍历思路:先序遍历的思想是左根右,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,当为空时转入最左节点的右子树,并访问,再重复上述过程直到栈和树均为空。

非递归实现二叉树的后序遍历思路:先序遍历的思想是左右根,先申请一个栈,在栈或树非空的情况下,先向左将节点压入栈,当为空时转入最左节点的右子树,如果右子树节点为空或被访问过,则访问,并记录当前节点为已访问节点,再重复上述过程直到栈和树均为空。

非递归实现二叉树的层次遍历思路:先申请一个队列,将根节点放到队列中,当此队列不为空时,访问头部节点,若此节点左孩子不为空,则将左孩子压入栈,若此节点右孩子不为空,则将右孩子压入栈,直到队列为空为止。

程序实现:

#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

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值