二叉树的遍历问题

二叉树的三种遍历方法

先序遍历

中序遍历

后序遍历

从上面的流程图不难看出,三种遍历方法均为递归定义,区别仅在于访问根节点的时间。

已知先序遍历和中序遍历,求后序遍历

对于一个二叉树的先序遍历,它的第一个值一定是该树的根节点。在中序遍历中找到该节点,那么在这个中序遍历中,该节点左边即是节点左子树对应的中序遍历,根据左子树的大小又可以确定左子树的先序遍历;该右边即是节点右子树对应的中序遍历,根据右子树的大小又可以确定右子树的先序遍历,递归求解即可。

P1827 [USACO3.4] 美国血统 American Heritage

#include<bits/stdc++.h>
using namespace std;
string pre,ino;
int n;
void pos(int lpre,int rpre,int lino,int rino){
    //printf("%d %d %d %d\n",lpre,rpre,lino,rino);
    if(lpre==rpre){
        cout<<pre[lpre];
        return;
    }
    if(lpre>rpre||lino>rino) return;
    char root=pre[lpre];
    int i;
    for(i=lino;i<=rino;i++){
        if(ino[i]==root) break;
    }
    pos(lpre+1,lpre+i-lino,lino,i-1);
    pos(rpre-rino+i+1,rpre,i+1,rino);
    cout<<root;
}
int main(){
    cin>>ino>>pre;
    n=pre.length();
    pos(0,n-1,0,n-1);
    return 0;
}

已知中序遍历和后序遍历,求先序遍历

对于一个二叉树的后序遍历,它的最后一个值一定是该树的根节点。类似上述方法递归求解即可。

P1030 [NOIP2001 普及组] 求先序排列

#include<bits/stdc++.h>
using namespace std;
string ino,pos;
int n;
void pre(int lino,int rino,int lpos,int rpos){
    if(lpos>rpos||lino>rino) return;
    cout<<pos[rpos];
    if(lino==rino) return;
    int i;
    for(i=lino;i<=rino;i++){
        if(ino[i]==pos[rpos]) break;
    }
    pre(lino,i-1,lpos,lpos+i-lino-1);
    pre(i+1,rino,rpos-rino+i,rpos-1);
}
int main(){
    cin>>ino>>pos;
    int n=ino.length();
    pre(0,n-1,0,n-1);
    return 0;
}

已知先序遍历和后序遍历,求可能的中序遍历的数量

已知二叉树的先序遍历和后序遍历,可能存在多种对应的二叉树,即存在多种可能的中序遍历。

首先,当二叉树中的某一节点只有左子树或只有右子树,对于该根节点,可能存在两种不同的二叉树,使其先序遍历和后序遍历相同,因此只需要找到这样的节点有x个,答案即为2^x。

一个二叉树的先序遍历可以这样描述: root->left->right;

一个二叉树的后序遍历可以这样描述:left->root->right;

如果一个二叉树只有左子树,则其先序遍历为:root->left,后序遍历为:left->root;

并且由于两种遍历方式的特性,root之后/之前的节点一定是其左子树的根节点,因此,如果root之后/之前的节点相同,则可以判定该根节点满足条件,x++,然后得出左子树的先序遍历和后序遍历继续搜索左子树。对于右子树也是一样的。

如果一个二叉树既有左子树,也有右子树,分别得出两个子树的先序遍历和后序遍历后,向下搜索两个子树即可。

P1229 遍历问题

#include<bits/stdc++.h>
using namespace std;
string pre,pos;
int x=0;
void ino(int lpre,int rpre,int lpos,int rpos){
    if(lpre>=rpre||lpos>=rpos) return;
    int l=rpre-lpre+1;
    //string pre_n=pre.substr(lpre,l),pos_n=pos.substr(lpos,l);
    if(pre[lpre+1]==pos[lpos+1]){
        x++;
        ino(lpre+1,rpre,lpos+1,rpos);
        return;
    }
    int i;
    for(i=lpre;i<=rpre;i++){
        if(pos[lpos+1]==pre[i]) break;
    }
    ino(i,rpre,lpos+1,lpos+1+rpre-i);
    ino(lpre+1,i-1,rpos-(i-2-lpre),rpos);
}
int main(){
    cin>>pre>>pos;
    reverse(pos.begin(),pos.end());
    int l=pre.length();
    ino(0,l-1,0,l-1);
    cout<<(long long)pow(2,x);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值