【洛谷二叉树】

17 篇文章 0 订阅
6 篇文章 0 订阅
本文介绍了洛谷平台上的几个二叉树题目,涉及二叉树的概念、性质、存储结构及遍历方法。包括基于线段树的建树问题、二叉树深度计算、遍历顺序的确定性问题以及树上前缀和的计算等,通过具体代码展示了解题思路和技巧。
摘要由CSDN通过智能技术生成

【数据结构1-2】二叉树 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

就是一个而二叉树洛谷官方题单

并没有写完,还差两道题,但是已经急着来写了QwQ(感觉那两题太难就润了

主要考察的是

二叉树的:

概念

性质

存储结构

遍历

总之就是很基础很简单的题

一、P4715 【深基16.例1】淘汰赛

P4715 【深基16.例1】淘汰赛 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

考的是已知二叉树最底层,怎么建树

其实这个就是线段树的build

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=2e2+10;
map<int,int> mp;
int n;
int a[mxn],tree[mxn<<1];
void pushup(int rt){
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
void build(int rt,int l,int r){
    if(l==r){
        tree[rt]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void solve(){
    cin>>n;
    for(int i=1;i<=(1<<n);i++) cin>>a[i],mp[a[i]]=i;
    build(1,1,1<<n);
    cout<<mp[min(tree[2],tree[3])]<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}

二、P4913 【深基16.例3】二叉树深度

P4913 【深基16.例3】二叉树深度 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

考的是二叉树怎么存储,一般用结构体存二叉树,就和线段树那种差不多,这样建的好处在于你可以递归建树

#include <bits/stdc++.h>
using namespace std;
const int mxe=1e6+10,mxn=1e6+10;
struct ty{
    int l,r;
}tree[mxe<<1];
int n;
int u,v,ans;
int vis[mxn];
void dfs(int u,int fa,int dep){
    ans=max(ans,dep);
    if(!vis[tree[u].l]&&tree[u].l!=0) vis[tree[u].l]=1,dfs(tree[u].l,u,dep+1);
    if(!vis[tree[u].r]&&tree[u].r!=0) vis[tree[u].r]=1,dfs(tree[u].r,u,dep+1);
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>u>>v;
        tree[i].l=u;
        tree[i].r=v;
    }
    dfs(1,-1,1);
    cout<<ans<<'\n';
}

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

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

典中典之二叉树的遍历顺序问题

已知中序和前序或中序和后序,求另外一个直接递归就好了

#include <bits/stdc++.h>
using namespace std;
void dfs(int x1,int y1,int x2,int y2);
string p1,p2;
int main(){
    cin>>p1>>p2;
    dfs(0,p1.length()-1,0,p2.length()-1);
    return 0;
}
void dfs(int x1,int y1,int x2,int y2){
    if(x1>y1||x2>y2) return;
    else{
        char x=p2[x2];
    for(int i=0;i<p1.length();i++){
        if(x==p1[i]){
            dfs(x1,i-1,x2+1,x2-x1+i);
            dfs(i+1,y1,y2-y1+i+1,y2);
            printf("%c",x);
        }
    }
    }
}

四、P1229 遍历问题

P1229 遍历问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

考的是二叉树遍历的不确定性

首先是一个结论:给定二叉树的前序和后序遍历,其中序遍历是不确定的,只有一个儿子结点的结点会影响确定性

充分性的原因是,如果一个结点只有一个儿子结点,那么这个儿子结点可以作为左结点,也可以作为右结点,而无论是左还是右,在前序遍历和后序遍历中的结果是一样的,但是在中序遍历中不一样

必要性的原因可以用反证法:假设一个结点有两个儿子结点

那么前序遍历是:根左右

后序遍历是:左右根

根确定,左的长度确定,这样就是一一对应过去,所以右也确定了

记只有一个儿子的结点有ans个

然后给定前序和后序,中序有(1<<ans)个,这里是乘法原理

#include <bits/stdc++.h>
using namespace std;
const int mxe=2e5+10,mxn=5e5+10;
string s1,s2;
void solve(){
    cin>>s1>>s2;
    int ans=0;
    for(int i=0;i<s1.size();i++){
        for(int j=1;j<s2.size();j++){
            if(s1[i]==s2[j]&&s1[i+1]==s2[j-1]) ans++;
        }
    }
    cout<<(1<<ans)<<'\n';
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}

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

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

这个和前面那个是一样的道理

#include <bits/stdc++.h>
using namespace std;
string s1,s2;
int ansi;
void dfs(int l1,int r1,int l2,int r2){
    if(l1>r1||l2>r2) return;
    for(int i=0;i<s1.size();i++){
        if(s1[i]==s2[r2]){
            cout<<s2[r2];
            dfs(l1,i-1,l2,i-l1+l2-1);
            dfs(i+1,r1,r2-r1+i,r2-1);
        }
    }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>s1>>s2;
    dfs(0,s1.size()-1,0,s2.size()-1);
}

六、P3884 [JLOI2009]二叉树问题

P3884 [JLOI2009]二叉树问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

树上前缀和裸题,直接上板子即可

#include <bits/stdc++.h>
using namespace std;
const int mxe=1e6+10,mxn=1e6+10;
struct ty{
    int to,next;
}edge[mxe<<1];
map<int,int> mp;
queue<int> q;
int n,u,v,rt,tot=0,a,b,mxdep=-1;
int head[mxn],vis[mxn],dep[mxn],f[mxn][65];
void add(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    tot=0;
    for(int i=0;i<=n;i++){
        head[i]=-1;
    }
}
void bfs(){
    memset(dep,0x3f,sizeof(dep));
    memset(vis,0,sizeof(vis));
    dep[0]=0,dep[1]=1;
    q.push(1),vis[1]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];~i;i=edge[i].next){
            if(vis[edge[i].to]) continue;
            vis[edge[i].to]=1;
            dep[edge[i].to]=dep[u]+1;
            q.push(edge[i].to);
            f[edge[i].to][0]=u;
            for(int j=1;j<=30;j++){
                f[edge[i].to][j]=f[f[edge[i].to][j-1]][j-1];
            }
        }
    }
}
int lca(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int k=30;k>=0;k--){
        if(dep[f[u][k]]>=dep[v]){
            u=f[u][k];
        }
    }
    if(u==v) return u;
    for(int k=30;k>=0;k--){
        if(f[u][k]!=f[v][k]){
            u=f[u][k];
            v=f[v][k];
        }
    }
    return f[u][0];
}
void solve(){
    cin>>n;
    init();
    for(int i=1;i<=n-1;i++){
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    bfs();
    int mx=-1;
    for(int i=1;i<=n;i++){
        mx=max(mx,dep[i]);
        mp[dep[i]]++;
    }
    for(auto it:mp) mxdep=max(mxdep,it.second);
    cout<<mx<<'\n';
    cout<<mxdep<<'\n';
    cin>>a>>b;
    cout<<(dep[a]-dep[lca(a,b)])*2+dep[b]-dep[lca(a,b)]<<'\n';
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}

再加一题:(61条消息) 【二叉树】L2-006 树的遍历_lamentropetion的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷B3642是关于二叉树遍历的题目。具体要求如下: 1. 对给定的二叉树进行先序、中序、后序和层次遍历,并输出结点的遍历序列。 2. 求二叉树的深度、结点数目和叶结点数目。 3. 可选做的题目是将二叉树的每个结点的左右子树交换位置。 根据引用的经验,可以采用深度优先搜索(DFS)的方式来遍历二叉树,通过先序遍历的顺序来求各个子树的结点。首先,在DFS的函数中,找到后序遍历的最后一个结点作为根结点,并根据根结点将字符串s1和s2划分为左子树和右子树的字符串。然后,递归地对左子树和右子树进行DFS。最后,输出根结点的值。这样就可以得到先序遍历的结果。 对于中序遍历和后序遍历的结果,可以通过相应的位置关系计算得到。例如,在DFS的过程中,可以在输出根结点之前输出左子树的结点,然后再输出右子树的结点,即可得到中序遍历的结果。同样地,在输出根结点之后,依次输出左子树和右子树的结点,即可得到后序遍历的结果。 至于层次遍历,可以使用队列的方式来实现。从根结点开始,依次将每个结点的左子树和右子树加入队列,并在出队的时候输出结点的值,直到队列为空。 综上所述,可以按照如下步骤来解答洛谷B3642题目: 1. 设计一个DFS函数,用于遍历二叉树并输出先序遍历的结果。 2. 在DFS函数中,根据后序遍历的特点找到根结点,并将s1和s2划分为左子树和右子树的字符串。 3. 在DFS函数中,递归地对左子树和右子树进行DFS,并在输出根结点之前或之后输出结点的值,从而得到中序和后序遍历的结果。 4. 设计一个层次遍历函数,使用队列的方式按层遍历二叉树,并输出结点的值,直到队列为空。 5. 根据题目要求,计算二叉树的深度、结点数目和叶结点数目。 请注意,以上步骤是一种可能的解答方案,你可以根据自己的理解和方法进行解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [4/9学习日记](https://blog.csdn.net/qq_74042166/article/details/130048431)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [二叉树_二叉树遍历_](https://download.csdn.net/download/weixin_42683394/27951460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值