树堆的建立与遍历

L2-011 玩转二叉树 (25 分)

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

输入格式:

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

输出格式:

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

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int z[maxn],qq[maxn],tree[maxn],ans[maxn];
queue<int> q;
void build(int n,int zl,int zr,int qql,int qqr)
{
    if(zl>zr||qql>qqr) return ;
    if(zl==zr){
        tree[n]=z[zl];return ;
    }
    for(int i=zl;i<=zr;i++)
    {
        if(z[i]==qq[qql])
        {
            tree[n]=qq[qql];
            build(2*n+2,i+1,zr,qql+i-zl+1,qqr);
            build(2*n+1,zl,i-1,qql+1,qqr+i-zl);
            break;
        }
    }
}
void bfs(int x)
{
    q.push(x);
    int l=0;
    while(!q.empty())
    {
        int y=q.front();
        q.pop();
        if(tree[y]==0) continue;
        ans[l++]=tree[y];
        q.push(2*y+2);
        q.push(2*y+1);
    }
}
int main()
{
    int n;
    cin>>n;
    memset(tree,0,sizeof(tree));
    memset(ans,0,sizeof(ans));
    for(int i=0;i<n;i++)
        cin>>z[i];
    for(int i=0;i<n;i++)
        cin>>qq[i];
    build(0,0,n-1,0,n-1);
    bfs(0);
    for(int i=0;i<n;i++){
        if(i!=n-1) printf("%d ",ans[i]);
        else printf("%d\n",ans[i]);
    }
    return 0;
}

L2-004 这是二叉搜索树吗? (25 分)

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点,

  • 其左子树中所有结点的键值小于该结点的键值;
  • 其右子树中所有结点的键值大于等于该结点的键值;
  • 其左右子树都是二叉搜索树。

所谓二叉搜索树的“镜像”,即将所有结点的左右子树对换位置后所得到的树。

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

输入格式:

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

输出格式:

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

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
int q[1005],n,mirror;
vector<int> h;
void get(int l,int r)
{
    if(l>r) return ;
    int i=l+1,j=r;
    if(mirror==0){
        while(i<=r&&q[i]<q[l]) i++;
        while(j>=l+1&&q[j]>=q[l]) j--;
    }
    else{
        while(i<=r&&q[i]>=q[l]) i++;
        while(j>=l+1&&q[j]<q[l]) j--;
    }
    //printf("%d %d\n",i,j);
    if(i!=j+1) return ;
    get(l+1,j);
    get(i,r);
    h.push_back(q[l]);
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>q[i];
    }
    mirror=0;
    get(0,n-1);
    if(h.size()<n){
        mirror=1;
        h.clear();
        get(0,n-1);
    }
    if(h.size()==n){
        cout<<"YES"<<endl;
        for(int i=0;i<n;i++){
            if(i!=n-1) cout<<h[i]<<" ";
            else cout<<h[i]<<endl;
        }
    }
    else{
        cout<<"NO"<<endl;
    }
    return 0;
}

L2-006 树的遍历 (25 分)

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

输入格式:

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

输出格式:

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

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int z[maxn],h[maxn],tree[maxn],ans[maxn];
queue<int> q;
void build(int n,int zl,int zr,int hl,int hr)
{
    if(zl>zr||hl>hr) return ;
    if(zl==zr){
        tree[n]=z[zl];return ;
    }
    for(int i=zl;i<=zr;i++)
    {
        if(z[i]==h[hr])
        {
            tree[n]=h[hr];
            build(2*n+1,zl,i-1,hl,hl+i-1-zl);
            build(2*n+2,i+1,zr,hl+i-zl,hr-1);
            break;
        }
    }
}
void bfs(int x)
{
    q.push(x);
    int l=0;
    while(!q.empty())
    {
        int y=q.front();
        q.pop();
        if(tree[y]==0) continue;
        ans[l++]=tree[y];
        q.push(2*y+1);
        q.push(2*y+2);
    }
}
int main()
{
    int n;
    cin>>n;
    memset(tree,0,sizeof(tree));
    memset(ans,0,sizeof(ans));
    for(int i=0;i<n;i++)
        cin>>h[i];
    for(int i=0;i<n;i++)
        cin>>z[i];
    build(0,0,n-1,0,n-1);
    bfs(0);
    for(int i=0;i<n;i++){
        if(i!=n-1) printf("%d ",ans[i]);
        else printf("%d\n",ans[i]);
    }
    return 0;
}

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

  • x is the rootx是根结点;
  • x and y are siblingsxy是兄弟结点;
  • x is the parent of yxy的父结点;
  • x is a child of yxy的一个子结点。

输入格式:

每组测试第1行包含2个正整数N(≤ 1000)和M(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出T,否则输出F

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,m,x,a[maxn],cnt,i;
map<int,int> mm;
void join(int x)
{
    cnt++;
    for(i=cnt;a[i/2]>x;i/=2){
        if(i==1) break;
        a[i]=a[i/2];
    }
    a[i]=x;
}
int main()
{
    cnt=0;
    cin>>n>>m;
    memset(a,0,sizeof(a));
    for(int i=0;i<n;i++){
        cin>>x;
        join(x);
    }
    for(int i=1;i<=n;i++){
        mm[a[i]]=i;
    }
    string s,ss,sss,ssss;
    int aa,bb;
    for(int i=0;i<m;i++){
        cin>>aa;
        cin>>s;
        if(s=="is"){
            cin>>ss;
            if(ss=="the"){
                cin>>sss;
                if(sss=="root"){
                    if(mm[aa]==1) cout<<"T"<<endl;
                    else cout<<"F"<<endl;
                }
                else{
                    cin>>ssss>>bb;
                    if(mm[aa]==mm[bb]/2) cout<<"T"<<endl;
                    else cout<<"F"<<endl;
                }
            }
            else{
                cin>>sss>>ssss>>bb;
                if(mm[aa]/2==mm[bb]) cout<<"T"<<endl;
                else cout<<"F"<<endl;
            }
        }
        else{
            cin>>bb>>sss>>ssss;
            if(mm[aa]/2==mm[bb]/2) cout<<"T"<<endl;
            else cout<<"F"<<endl;
        }
    }
    return 0;
}

HDU3999

建立二叉搜索树 输出它的层序遍历

用结构体数组下标表示该节点的值,左右子树为它的左右值,用while(1)循环建立树,如果该节点不可以,转换到下一左或右节点。

用dfs输出时,如果没有值,跳过,有值,记录再遍历它的左右子树。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const double pi=acos(-1);
const int maxn=1e5+5;
int n,root,ans[maxn];
struct node
{
    int l,r;
}tree[maxn];
void join(int x)
{
        int y=root;
        while(1){
             if(x>y){
                 if(!tree[y].r){
                    tree[y].r=x;return ;
                 }
                 else y=tree[y].r;
             }
             else{
                if(!tree[y].l){
                    tree[y].l=x;return ;
                }
                else y=tree[y].l;
             }
        }
}
int l=0;
void dfs(int y){
    if(y==0) return ;
    ans[l++]=y;
    dfs(tree[y].l);
    dfs(tree[y].r);
}
int main()
{
    cin>>n;
    int x;
    memset(tree,0,sizeof(tree));
    for(int i=0;i<n;i++){
        cin>>x;
        if(i==0) root=x;
        else join(x);
    }
    dfs(root);
    for(int i=0;i<n;i++){
        if(i!=n-1) printf("%d ",ans[i]);
        else printf("%d\n",ans[i]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值