非递归遍历二叉树

/*******************************************************
 >非递归遍历二叉树(先序、中序、后序遍历)
 *****************************************************/


#include<iostream>
#include<stack>
using namespace std;

struct node{ //定义树节点
    char ch;
    node *left,*right;
};

node *creat();

void preorder( node *root );
void inorder( node* root );
void postorder( node *root );
int main()
{
    node *root = creat();

    cout << "先序遍历:";
    preorder( root );

    cout << "中序遍历:";
    inorder( root );

    cout << "后序遍历:";
    postorder( root );

    return 0;
}

node *creat() //按先序遍历创建一棵树
{
    node *root = new node;
    char ch;
    cin >> ch;
    if( ch == '#' )
    {
        root = NULL;
    }
    else
    {
        root->ch = ch;
        root->left = creat();
        root->right = creat();
    }
    return root;
}

void preorder( node *root )//先序遍历
{
    if( root == NULL )
        return;
    node *p = root;
    stack<node *> s;
    while( !s.empty() || p )
    {
        if( p )
        {
            cout << p->ch << " ";//输出根节点
            s.push( p );
            p = p->left;//进入左
        }
        else//左子树空了 进入右子树
        {
            p = s.top();
            s.pop();
            p = p->right;//进入右
        }
    }
    cout << endl;
}

void inorder( node *root ) //中序遍历
{
    if( root == NULL )
    return ;
    //树非空
    node *p = root;
    stack<node *> s;
    while( !s.empty() || p )
    {
        if( p ) // 向左遍历到底
        {
            s.push( p );
            p = p->left;
        }
        else //进入右子树
        {
            p = s.top(); //取栈顶元素 这时p还是左孩子 将根节点赋给p
            s.pop();
            cout << p->ch << " ";
            p = p->right;
        }
    }
    cout << endl;
}

void postorder( node *root )//后序遍历 难点在于需要判断上一个访问的是左子树还是右子树,若是左需要跳过跟访问右
{
    if( root == NULL )
        return ;
    stack< node *> s;
    node *p1,*p2;//p1为当前访问节点,p2为上次访问节点
    p1 = root;
    while( p1 )
    {
        s.push( p1 );
        p1 = p1->left;
    }
    //此时p1为空,走到左子树底端
    while( !s.empty() )
    {
        p1 = s.top();
        s.pop();
        //能访问根节点的前提是它无右子树或右子树已经被访问过
        if( p1->right == NULL || p1->right == p2 )
        {
            cout << p1->ch << " ";
            p2 = p1;
        }
        else
        {
            //根节点再次入栈
            s.push( p1 );
            //进入右子树
            p1 = p1->right;
            while( p1 )
            {
                s.push( p1 );
                p1 = p1->left;
            }
        }
    }
    cout << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值