数据结构:二叉树的前序,中序,后序遍历(递归和非递归)

二叉树的使用,在数据结构中是比较常见的。这里列举了二叉树的四种遍历方式:前序,中序,后序遍历(递归和非递归的方式)以及层次遍历的方法,供大家参考。

先给出文章中所用的二叉树:

         8

      /             \

    6               10

  /          \          /        \

 5           7     9         11

   \         /        /                \

  12    16    13               15

                        \

                        14

首先是前序遍历:

递归的方式:

1.  遍历根节点

2.  遍历左子树

3.  遍历右子树

void preOrser(TreeNode *s)
{
    if ( s != nullptr )
    {
        cout << s->val << "  ";  
        preOrser(s->left);
        preOrser(s->right);
    }
}
非递归的方式:详细解释见注释

void preOrser(node *t)
{
    //  用于保存节点
    stack<node*> s;

    if ( t == nullptr )
        return;
    // 当指针非空,或者 栈非空时 继续遍历
    while( t || !s.empty() )
    {
        // 一直找到最左端
        while(t)
        {
            // 因为是先序遍历,所以需要先打印节点的值
            cout << t->val << " " ;
            s.push( t );
            t = t->left;
        }  // 当空节点时,跳出循环

        t = s.top();
        s.pop();
        //  找到右孩子
        t = t->right;
    }
}


其次是中序遍历:

递归的方式:

1.  遍历左子树

2.  遍历根节点

3.  遍历右子树

void midOrder(TreeNode *s)
{
    if ( s != nullptr )
    {
        midOrder(s->left);
        cout << s->val << "  ";
        midOrder(s->right);
    }
}


非递归的方式:

//  完成了二叉树的中序遍历的非递归形式
//  通过 栈 能实现二叉树的遍历过程
void midOrder(node *t)
{
    //  用于储存遍历的元素
    stack<node*> sta;
    while( t ||  !sta.empty() )
    {
        if ( t != nullptr )
        {
            sta.push(t);
            t = t->left;
        }
        else
        {
            t = sta.top();
            sta.pop();
            cout << t->val << " ";
            t = t->right;
        }
    }
}

再则是后续遍历:

1.  遍历左子树

2.  遍历右子树

3.  遍历根节点

void postOrder(TreeNode *s)
{
    if ( s != nullptr )
    {
        postOrder(s->left);
        postOrder(s->right);
        cout << s->val << "  ";
    }
}


非递归的方式:

//非递归实现二叉树后续遍历,需要借助两个容器来实现 
//第一个栈按前序遍历将二叉树节点压栈 
//第二个容器是当第一个栈要出栈的时候,将当前出栈的节点压栈到第二个容器 
//如果当前节点存在左孩子节点,则压栈到第一个栈 
//如果当前节点存在右孩子节点,则压栈到第一个栈 
//最后当第一个栈为空的时候,这时候遍历第二个容器,让第二个容器一直输出当前节点值 
void postOrser(node *t)
{
    stack<node*> pre;
    vector<int> post;
    if ( t == nullptr )
        return;
    pre.push(t);

    while( !pre.empty() )
    {
        node* p;
        p = pre.top();
        post.push_back(p->val);
        pre.pop();
        if ( p->left != nullptr )
            pre.push(p->left);
        if ( p->right != nullptr )
            pre.push(p->right);
    }
    for ( auto it = post.end() -1; it >= post.begin(); it-- )
        cout << *it << " ";
}



最后给出层次遍历的方法:

层次遍历就是按照二叉树的高度,从上往下,从左向右依次遍历每一个节点

vector<int> PrintFromTopToBottom(TreeNode *root)
{

    vector<struct TreeNode*> v;
    vector<int> s;
    if ( root == nullptr )
        return s;
    v.push_back(root);
    int i = 0;
    while(i != v.size())
    {
        if ( v[i]->left != nullptr )
        {
             v.push_back(v[i]->left);
        }
        if ( v[i]->right != nullptr )
        {
            v.push_back(v[i]->right);
        }
        i++;
    }
    for ( int i = 0 ; i < v.size();i++ )
    {
        s.push_back(v[i]->val);
    }
    return s;
}

以上所有程序的执行结果对应上面的二叉树为:







  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值