二叉树的遍历方式

二叉树概念

二叉树遍历方式

广度优先遍历(层序遍历)

在这里插入图片描述
规则:从上往下对每一层操作,在每一层中,从左至右访问节点
上图遍历结果:root->A->B->C->D->E
注意:对于层序遍历方式,一般借助队列来实现。
如题剑指offer:从上往下打印二叉树

深度优先遍历

规则:对每一个可能的分支路径深入到尽头为止,且每个节点之访问一次。注意:二叉树的深度优先遍历可细分为先序,中序,后序遍历。
先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。

上图遍历结果:
先序:root->A->C->D->B->E
中序:C->A->D->root->B->E
后序:C->D->A->E->B->root

注意:对于以上三种深度优先遍历方式,可采用递归实现,也可采用栈实现,因为递归的本质就是压栈和出栈。

例子

先序遍历-栈实现:

根据先序的规则,使用一个栈s保存待访问的节点,使用p保存当前正在访问的节点,p从根节点开始。一路沿着左子树向下走,直到p为空时,在通过栈进行回退。
根左右:在指针迭代时访问节点值。

void PreShow2(TreeNode* root) //先序栈
{
    if(!root) return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    while (p != nullptr|| !s.empty())
    {
        while(p) //沿着左子树往下走,访问途中节点并压栈保存。
        {
            cout<<p->val<<' ';
            s.push(p);
            p = p->left;
        }
        p = s.top(); //将父节点出栈,并访问其右子树
        s.pop();
        p=p->right;
    }
}
中序遍历-栈实现:

算法思想同先序。
左根右:在栈顶访问结点值
沿着左子树到底,此时只是将途中节点压栈保存,不访问。直至p为空,访问此时栈顶元素

void InShow2(TreeNode*root) //中序栈
{
    if(!root)   return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    while(p!=nullptr || !s.empty())
    {
        while(p)
        {
            s.push(p);
            p=p->left;
        }
        p=s.top();//此时访问父节点元素,并将父节点出栈。
        cout<<p->val<<' ';
        s.pop();
        p=p->right;
    }
}
后序遍历-栈实现

后序遍历相对复杂一点,因为后序是左根右,在使用栈来存储节点时,需要分清楚出栈时的节点是从左子树返回的还是右子树返回的。所以需要一个temp表示p上一次表示的节点。

void PostShow2(TreeNode*root) //后序栈
{   
    if(!root) return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    TreeNode *temp = NULL;
    while(p!=nullptr||!s.empty())
    {   
        while(p)
        {   
            s.push(p);
            p=p->left;
        }
        p=s.top();
        if(p->right ==NULL||p->right == temp) //如果p没有右孩子或则其右孩子刚刚被访问过
        {   
            cout<<p->val<<' ';  则访问p节点并将其从栈中删除
            s.pop(); 
            temp = p;  //标记最近被访问的节点。
            p = NULL;
        }
        else
        {   
            p=p->right;
        }
    }
}
层序遍历-队列实现:

见:剑指offer_t22_从上往下打印二叉树

代码实现

在这里插入图片描述
使用c++11编译
采用栈和队列实现

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


struct TreeNode{
    int val;
    struct TreeNode * left;
    struct TreeNode * right;
    TreeNode(int x):
        val(x),left(NULL),right(NULL){
    }

};

vector<int> censhow(TreeNode * root) //层序
{
    vector<int> result;
    if(!root)   return result;
    queue<TreeNode*> q;
    q.push(root);
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        result.push_back(t->val);
        if(t->left)     q.push(t->left);
        if(t->right)    q.push(t->right);
    }
    return result;
}

void print(vector<int> & arr) //层序打印
{
    for(vector<int>::iterator it = arr.begin();it != arr.end();it++)
        cout<<*it<<" ";
    cout<<endl;
}

void PreShow1(TreeNode* root) //先序递归
{
    if(!root) return;
    cout<<root->val<<' ';
    if(root->left)
        PreShow1(root->left);
    if(root->right)
        PreShow1(root->right);
}

void PreShow2(TreeNode* root) //先序栈
{
    if(!root) return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    while (p != nullptr|| !s.empty())
    {
        while(p)
        {
            cout<<p->val<<' ';
            s.push(p);
            p = p->left;
        }
        p = s.top()->right;
        s.pop();
    }
}

void InShow1(TreeNode*root) //中序递归
{
    if(!root) return;
    if(root->left)
        InShow1(root->left);
        cout<<root->val<<' ';
    if(root->right)
        InShow1(root->right);
}

void InShow2(TreeNode*root) //中序栈
{
    if(!root)   return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    while(p!=nullptr || !s.empty())
    {
        while(p)
        {
            s.push(p);
            p=p->left;
        }
        p=s.top();
        cout<<p->val<<' ';
        s.pop();
        p=p->right;
    }
}

void PostShow1(TreeNode*root) //后序递归
{   
    if(!root)   return;
    if(root->left)  PostShow1(root->left);
    if(root->right) PostShow1(root->right);
    cout<<root->val<<' ';
}

void PostShow2(TreeNode*root) //后序栈
{   
    if(!root) return;
    stack<TreeNode*> s;
    TreeNode *p = root;
    TreeNode *temp = NULL;
    while(p!=nullptr||!s.empty())
    {   
        while(p)
        {   
            s.push(p);
            p=p->left;
        }
        p=s.top();
        if(p->right ==NULL||p->right == temp)
        {   
            cout<<p->val<<' ';
            s.pop(); 
            temp = p;
            p = NULL;
        }
        else
        {   
            p=p->right;
        }
    }
}
int main()
{
    TreeNode* l1 = new TreeNode(1);
    TreeNode* l2 = new TreeNode(2);
    TreeNode* l3 = new TreeNode(3);
    TreeNode* l4 = new TreeNode(4);
    TreeNode* l5 = new TreeNode(5);
    TreeNode* l6 = new TreeNode(6);
    TreeNode* l7 = new TreeNode(7);
    l1->left = l2; 
    l1->right = l3;
    l2->left = l4;
    l2->right = l5;
    l3->left = l6;
    l3->right = l7;
    
    vector<int> a = censhow(l1);
    cout<<"层序遍历:"<<endl;
    print(a);
    
    cout<<"先序递归:"<<endl;
    PreShow1(l1);
    cout<<"\n";
    
    cout<<"先序栈:"<<endl;
    PreShow2(l1);
    cout<<"\n";
    
    cout<<"中序递归:"<<endl;
    InShow1(l1);
    cout<<"\n";
    
    cout<<"中序栈:"<<endl;
    InShow2(l1);
    cout<<"\n";
    
    cout<<"后序递归:"<<endl;
    PostShow1(l1);
    cout<<"\n";
    
    cout<<"后序栈"<<endl;
    PostShow2(l1);
    cout<<"\n";
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

通信仿真爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值