1.20总结

二叉树的遍历 

1.已知中序遍历和后序遍历,得到先序遍历。

P1030 [NOIP2001 普及组] 求先序排列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

例如:中序ACGDBHZKX,后序CDGAHXKZB,首先可找到主根B;

那么我们找到中序遍历中的B,由这种遍历的性质,可将中序遍历分为ACGD和HZKX两棵子树,

那么对应可找到后序遍历CDGA和HXKZ(从头找即可)

从而问题就变成求1.中序遍历ACGD,后序遍历CDGA的树 2.中序遍历HZKX,后序遍历HXKZ的树;

接着递归,按照原先方法,找到1.子根A,再分为两棵子树2.子根Z,再分为两棵子树。

就按这样一直做下去(先输出根,再递归);

模板概括为step1:找到根并输出

step2:将中序,后序各分为左右两棵子树;

step3:递归,重复step1,2;

图中即为先序遍历、中序遍历、后序遍历。

代码实现

#include<stdio.h>
#include<string.h>
char zx[10],hx[10];
int len;
void fun(int zl,int zr,int hl,int hr)
{
    printf("%c",hx[hr-1]);//打印根结点
    int u;//标记根结点的位置
    for(int i=zl; i<zr; i++)
    {
        if(zx[i]==hx[hr-1])//找出根结点在中序遍历的位置,然后进行标记
            u=i;
    }
    if(u-zl>0)//有左子树
        fun(zl,u,hl,hl+u-zl);
    if(zr-u-1>0)//有右子树
        fun(u+1,zr,hr-zr+u,hr-1);
}
int main()
{
    void fun(int zl,int zr,int hl,int hr);
    scanf("%s",zx);
    scanf("%s",hx);
    len=strlen(zx);//反正长度一样
    fun(0,len,0,len);
    return 0;
}

2.已知先序遍历、中序遍历,得到后续遍历。

P1827 [USACO3.4]美国血统 American Heritage - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

这个其实和上面一个差不多,不同就是要在最后输出根结点,还有左右子树的范围。

代码实现

#include<stdio.h>
#include<string.h>
char zx[30],qx[30];
int len;
void fun(int ql,int qr,int zl,int zr)
{
    int u;
    for(int i=zl;i<zr;i++)
    {
        if(zx[i]==qx[ql])//标记根结点
        {
            u=i;
        }
    }
    if(u-zl>0)//有左子树
        fun(ql+1,ql+u+1-zl,zl,u);
    if(zr-u-1>0)//有右子树
        fun(qr-zr+u+1,qr,u+1,zr);
    printf("%c",qx[ql]);//打印根结点
}
int main()
{
    void fun(int ql,int qr,int zl,int zr);
    scanf("%s",zx);
    scanf("%s",qx);
    len=strlen(zx);
    fun(0,len,0,len);
    return 0;
}

3.输出二叉树的先序遍历。

P1305 新二叉树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路

原来的思路是只用一个main函数,而不自定义函数,但这样的话就要写很多的for循环,特别绕,然后就改变了一下思路,自定义一个函数,用递归来不断找到结点,题目说了每一行每一个字母为节点,后两个字母分别为其左右儿子,如果这个结点用*表示,就是空的,没有左右子树,不需要在往下遍历这个结点。

代码实现

#include<stdio.h>
/*typedef struct Bnode
{
    char data;//存储结点元素的值
    struct Bnode *lchild;//指向左孩子
    struct Bnode *rchile;//指向右孩子
}BiNode,*BiTree;
void PreOrderTraverse(BiTree T)
{
    if(T!=NULL)//二叉树非空
    {
        printf("%c",T->data);//根结点
        PreOrderTraverse(T->lchild);//先序遍历左子树
        PreOrderTraverse(T->rchild);//先序遍历右子树
    }
}*/
int n;
char s[30][5];
void fun(char u)
{
    if(u!='*')
    {
        printf("%c",u);
        for(int i=0;i<=n;i++)
        {
            if(s[i][0]==u)
            {
                fun(s[i][1]);
                fun(s[i][2]);
            }
        }
    return;
    }
    else
        return;
}
int main()
{
    void fun(char v);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%s",s[i]);
    fun(s[0][0]);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值