SDUT数据结构PTA专题(实验五)题解

53 篇文章 8 订阅
10 篇文章 0 订阅

7-1 还原二叉树 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

int n;  // 节点数
char pre[N];  // 记录前序遍历
char mid[N];  // 记录中序遍历

struct node{  // 树结构体
    char data;
    node *l,*r;
};

node *buildtree(int len,char *pre,char *mid){  // 建树
    node *root=new node;
    if(!len) return NULL;  // 返回空节点
    root->data=pre[0];  // 前序遍历第一个值为根节点
    int i;
    for(i=0;i<len;i++){  // 在中序遍历中找到对应根节点
        if(mid[i]==pre[0]) break;
    }
    root->l=buildtree(i,pre+1,mid); // 构建左子树
    root->r=buildtree(len-i-1,pre+i+1,mid+i+1);  // 构建右子树
    return root;
}

int get_high(node *root){  // 获取高度
    int res=0;
    int hl=0,hr=0;
    if(!root) res=0;
    else{
        hl=get_high(root->l);  // 获取左子树高度
        hr=get_high(root->r);  // 获取右子树高度
        res=max(hl,hr)+1;      // 最高子树高度+1
    }
    return res;  //  返回高度
}

inline void solve(){
    cin>>n;  // 输入节点数
    cin>>pre>>mid;  // 输入前序、中序
    node *root=buildtree(n,pre,mid); // 建树
    cout<<get_high(root)<<endl;  // 输出高度
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

7-2 朋友圈 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

int vis[N];
int num[N];

void init(int n){  // 初始化
    for(int i=0;i<=n;i++) vis[i]=i;
}

int Find(int x){ // 并查集
    if(x!=vis[x]) vis[x]=Find(vis[x]);
    return vis[x];
}

void Merge(int x,int y){  // 合并
    int xx=Find(x);
    int yy=Find(y);
    if(xx!=yy) vis[xx]=yy;
}

inline void solve(){
    int n,m;
    cin>>n>>m;
    init(n);
    while(m--){
        int k,x,y;
        cin>>k;
        if(k){
            k--;
            cin>>x;
            while(k--){
                cin>>y;
                Merge(x,y);
            }
        }
    }
    int maxn=0;
    for(int i=1;i<=n;i++){
        int x=Find(i);
        num[x]++;
        maxn=max(maxn,num[x]);
    }
    cout<<maxn<<endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7-3 修理牧场 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

inline void solve(){
    int n;
    cin>>n;
    int x;
    priority_queue<int,vector<int>,greater<int> >p; //定义优先队列(小顶堆)
    for(int i=1;i<=n;i++){  // 输入每段长度,放入队中
        cin>>x;
        p.push(x);
    }
    int sum=0;  // 记录花费
    int a,b;
    while(p.size()>1){  // 没有变成一张根木棍
        a=p.top();p.pop();  // 取出最小元素
        b=p.top();p.pop();  // 取出次小元素
        sum+=a+b;  // 求当前最小费用
        p.push(a+b);  // 费用入队
    }
    cout<<sum<<endl;  // 输出答案
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7-4 树的遍历 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

int n;  // 节点数
int post[N];  // 记录后序遍历
int mid[N];  // 记录中序遍历

struct node{  // 树结构体
    int data;
    node *l,*r;
};

node *buildtree(int len,int *post,int *mid){  // 建树
    node *root=new node;
    if(!len) return NULL;  // 返回空节点
    root->data=post[len-1];  // 后序遍历第一个值为根节点
    int i;
    for(i=0;i<len;i++){  // 在中序遍历中找到对应根节点
        if(mid[i]==post[len-1]) break;
    }
    root->l=buildtree(i,post,mid); // 构建左子树
    root->r=buildtree(len-i-1,post+i,mid+i+1);  // 构建右子树
    return root;
}

void cengxu(node *root){  // 层序遍历(BFS)
    queue<node>q;  // 定义队列
    q.push(*root);  //根节点入队
    bool tag=0;
    while(q.size()){
        auto t=q.front();  //取出队首元素
        q.pop();  // 队首元素出队
        if(tag) cout<<" ";
        else tag=1;
        cout<<t.data; //输出值
        if(t.l) q.push(*t.l); // 若左子树不空,则放入左子树根节点
        if(t.r) q.push(*t.r); // 若右子树不空,则放入右子树根节点
    }
    cout<<endl;
}

inline void solve(){
    cin>>n;  // 输入节点数
    for(int i=0;i<n;i++) cin>>post[i];
    for(int i=0;i<n;i++) cin>>mid[i];
    node *root=buildtree(n,post,mid); // 建树
    cengxu(root);  //层序遍历
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    //cin>>t;
    while(t--) solve();
    return 0;
}

7-5 部落 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

int vis[N];

void init(int n){  // 初始化
    for(int i=0;i<=n;i++) vis[i]=i;
}

int Find(int x){  // 并查集
    if(x!=vis[x]) vis[x]=Find(vis[x]);
    return vis[x];
}

void Merge(int x,int y){  // 合并
    int xx=Find(x);
    int yy=Find(y);
    if(xx!=yy) vis[xx]=yy;
}

set<int>peo,num; // 记录人数和部落数

inline void solve(){
    int n;
    cin>>n;
    init(100000);
    for(int i=1;i<=n;i++){
        int k;
        cin>>k;
        if(k){
            int x,y;
            cin>>x;
            peo.insert(x);
            k--;
            while(k--){
                cin>>y;
                peo.insert(y);  // 记录人数
                Merge(x,y); // 合并
            }
        }
    }
    for(int i=1;i<=peo.size();i++) num.insert(Find(i));  // 记录部落数
    cout<<peo.size()<<" "<<num.size()<<endl;  // 输出人数和部落数
    int q;
    cin>>q;  //  q次询问
    while(q--){
        int x,y;
        cin>>x>>y;
        if(Find(x)!=Find(y)) cout<<"N"<<endl; // 不在一个部落
        else cout<<"Y"<<endl;  // 在一个部落
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7-6 交换二叉树中每个结点的左孩子和右孩子 (20 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

typedef struct node{
    char data;
    node *l,*r;
}*Bitree;

string s;
int pos;

void buildtree(Bitree &root){  // 建树
    if(s[pos]=='#'){
        root=NULL;
        pos++;
    }else{
        root=new node;
        root->data=s[pos++];
        buildtree(root->l);  // 建立左子树
        buildtree(root->r);  // 建立右子树
    }
}

void midorder(Bitree root){  // 中序遍历
    if(root){
        midorder(root->l);
        cout<<root->data;
        midorder(root->r);
    }
}

void exmidorder(Bitree root){  // 反向中序遍历(即交换左右子树)
    if(root){
        exmidorder(root->r);
        cout<<root->data;
        exmidorder(root->l);
    }
}

inline void solve(){
    cin>>s;
    pos=0;
    node *root=new node;
    buildtree(root);
    midorder(root);
    cout<<endl;
    exmidorder(root);
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7-7 列出叶结点 (25 分)

#include<bits/stdc++.h>
#define eb emplace_back
#define ll long long
const int N = 2e5 + 10;
using namespace std;

struct node{
    int l,r;
}tree[N];

int val[N];

queue<int>q;
vector<int>res;

void BFS(){  // 层序遍历找叶子
    while(q.size()){
        auto t=q.front();
        q.pop();
        if(tree[t].l==-1&&tree[t].r==-1) res.eb(t);
        if(tree[t].l!=-1) q.push(tree[t].l);
        if(tree[t].r!=-1) q.push(tree[t].r);
    }
}

inline void solve(){
    int n;
    cin>>n;
    char a,b;
    for(int i=0;i<n;i++){  // 建树
        cin>>a>>b;
        if(a=='-') tree[i].l=-1;
        else{
            tree[i].l=a-'0';
            val[a-'0']=1;
        }
        if(b=='-') tree[i].r=-1;
        else{
            tree[i].r=b-'0';
            val[b-'0']=1;
        }
    }
    int root;
    for(int i=0;i<n;i++){  // 找根节点
        if(!val[i]){
            root=i;
            break;
        }
    }
    q.push(root);
    BFS();
    bool tag=0;
    for(auto i:res){  // 输出结果
        if(tag) cout<<" ";
        else tag=1;
        cout<<i;
    }
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7-8 建立与遍历二叉树 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

typedef struct node{
    char data;
    node *l,*r;
}*Bitree;

string s;
int pos;

void buildtree(Bitree &root){  // 建树
    if(s[pos]=='#'){
        root=NULL;
        pos++;
    }else{
        root=new node;
        root->data=s[pos++];
        buildtree(root->l);  // 建立左子树
        buildtree(root->r);  // 建立右子树
    }
}

void midorder(Bitree root){  // 中序遍历
    if(root){
        midorder(root->l);
        cout<<root->data;
        midorder(root->r);
    }
}

inline void solve(){
    cin>>s;
    pos=0;
    node *root=new node;
    buildtree(root);
    midorder(root);
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7-9 完全二叉树的层序遍历 (25 分)

#include<bits/stdc++.h>
#define ll long long
const int N = 2e5 + 10;
using namespace std;

int n;
int root[N];

void buildtree(int x){  // 递归建树
    if(x>n) return ;
    buildtree(2*x);
    buildtree(2*x+1);
    cin>>root[x];
}

inline void solve(){
    cin>>n;
    buildtree(1); // 建树
    for(int i=0;i<n;i++){ // 输出结果
        if(i) cout<<" ";
        cout<<root[i+1];
    }
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值