天梯赛二叉树部分题解(建树)

以下题解是天梯赛中与二叉树相关的题采用建树的方法做的。
L2-004 这是二叉搜索树吗? (25 分)
这是二叉搜索树吗?
一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

其左子树中所有结点的键值小于该结点的键值;
其右子树中所有结点的键值大于等于该结点的键值;
其左右子树都是二叉搜索树。
所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

给定一个整数键值序列,现请你编写程序,判断这是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。

输入格式:
输入的第一行给出正整数 N(≤1000)。随后一行给出 N 个整数键值,其间以空格分隔。

输出格式:
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出 YES ,然后在下一行输出该树后序遍历的结果。数字间有 1 个空格,一行的首尾不得有多余空格。若答案是否,则输出 NO。

输入样例 1:
7
8 6 5 7 10 8 11
输出样例 1:
YES
5 7 6 8 11 10 8
输入样例 2:
7
8 10 11 8 6 7 5
输出样例 2:
YES
11 8 10 7 5 6 8
输入样例 3:
7
8 6 8 5 10 9 11
输出样例 3:
NO

思路:两种建数方法,通过pre[0]和pre[1]的大小判断是否镜像,然后用两种建树方法分别建树,在建树的过程中判断后序数组元素与该节点数据的大小来检查是否是二叉搜索树,然后通过后序遍历输出结果即可

#include<bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *l,*r;
};
int n;
int pre[1005];
int flag=0;
int sum=0;
node* create1(int l,int r)
{
    if(l>r)
        return NULL;
    node* root = new node;
    root->data=pre[l];
    int i;
    for(i=l+1;i<=r;i++)
        if(pre[i]>=pre[l])
        break;
    for(int j=i;j<=r;j++)
    {
        if(pre[j]<pre[l])
            flag=1;
    }
    root->l=create1(l+1,i-1);
    root->r=create1(i,r);
    return root;
}
node* create2(int l,int r)
{
    if(l>r)
        return NULL;
    node* root = new node;
    root->data=pre[l];
    int i;
    for(i=l+1;i<=r;i++)
        if(pre[i]<pre[l])
        break;
    for(int j=i;j<=r;j++)
        if(pre[j]>=pre[l])
        flag=1;
    root->l=create2(l+1,i-1);
    root->r=create2(i,r);
    return root;
}
void tprintf(node* root)
{
    if(root==NULL)
        return;
    tprintf(root->l);
    tprintf(root->r);
    sum++;
    if(sum<n)
    cout<<root->data<<" ";
    else
    cout<<root->data<<endl;
    return ;
}
int main()
{
    node* root = new node;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>pre[i];
    root->data=pre[0];
    flag=0;
    if(pre[0]>pre[1])
    {
        int i;
        for(i=1;i<n;i++)
            if(pre[i]>=pre[0])
                break;
        for(int j=i;j<=n-1;j++)
            if(pre[j]<pre[0])
            flag=1;
        root->l=create1(1,i-1);
        root->r=create1(i,n-1);
        if(flag)
        {
            cout<<"NO"<<endl;
            return 0;
        }
    }
    else
    {
        int i;
        for(i=1;i<n;i++)
            if(pre[i]<pre[0])
                break;
        for(int j=i;j<=n-1;j++)
            if(pre[j]>=pre[0])
            flag=1;
        root->l=create2(1,i-1);
        root->r=create2(i,n-1);
        if(flag)
        {
            cout<<"NO"<<endl;
            return 0;
        }
    }
    cout<<"YES"<<endl;
    tprintf(root);
}

L2-006 树的遍历 (25 分)
树的遍历
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2

思路:首先根据后序和中序建立二叉树,层序遍历可以将根节点和左右孩子节点按顺序入队,然后输出即可

#include<bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *l,*r;
};
int pre[105];
int post[105];
int in[105];
int n;
node* create(int postl,int postr,int inl,int inr)
{
    if(postl>postr)
        return NULL;
    node *root = new node;
    root->data=post[postr];
    int i;
    for(i=inl;i<=inr;i++)
        if(in[i]==post[postr])
            break;
    int k1=i-inl;
    root->l=create(postl,postl+k1-1,inl,i-1);
    root->r=create(postl+k1,postr-1,i+1,inr);
    return root;
}
void bfs(node* root)
{
    queue<node*>q;
    q.push(root);
    int m=0;
    while(!q.empty())
    {
        node* f=q.front();
        q.pop();
        m++;
        if(m<n)
        {
            cout<<f->data<<" ";
        }
        else
        cout<<f->data<<endl;
        if(f->l!=NULL) q.push(f->l);
        if(f->r!=NULL) q.push(f->r);
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>post[i];
    for(int i=0;i<n;i++)
        cin>>in[i];
    node* root=create(0,n-1,0,n-1);
    bfs(root);
    return 0;
}

L2-011 玩转二叉树 (25 分)
玩转二叉树
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。

输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。

输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2

思路:此题和上题的思路差不多,同样先建树,只是在bfs时会有区别,这里的bfs需要按照根节点->右孩子节点->左孩子节点的顺序进行入队,因为题目要求输出反转结果。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *l,*r;
};
int n;
int post[50];
int in[50];
int pre[50];
node* create(int prel,int prer,int inl,int inr)
{
    if(prel>prer)
        return NULL;
    node* root=new node;
    root->data=pre[prel];
    int i;
    for(i=inl;i<=inr;i++)
        if(in[i]==pre[prel])
        break;
    int k=i-inl;
    root->l=create(prel+1,prel+k,inl,i-1);
    root->r=create(prel+k+1,prer,i+1,inr);
    return root;
}
void bfs(node* root)
{
    queue<node*>q;
    q.push(root);
    int m=0;
    while(!q.empty())
    {
        node* f=q.front();
        q.pop();
        m++;
        if(m<n)
            cout<<f->data<<" ";
        else
            cout<<f->data<<endl;
        if(f->r!=NULL) q.push(f->r);
        if(f->l!=NULL) q.push(f->l);
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>in[i];
    for(int i=0;i<n;i++)
        cin>>pre[i];
    node* root = new node;
    root=create(0,n-1,0,n-1);
    bfs(root);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值