挑战程序设计竞赛 算法和数据结构 第8章 树

挑战程序设计竞赛 算法和数据结构 第8章 树

8.2 ALDS1_7_A:Rooted Trees

原书AC代码:

#include <iostream>
using namespace std;
#define MAX 100005
#define NIL -1
struct Node{int p,l,r;};
Node T[MAX];
int n,D[MAX];
void print(int u){
    int i,c;
    cout<<"node "<<u<<": ";
    cout<<"parent = "<<T[u].p<<", ";
    cout<<"depth = "<<D[u]<<", ";
    if(T[u].p==NIL)cout<<"root, ";
    else if(T[u].l==NIL)cout<<"leaf, ";
    else cout<<"internal node, ";
    cout<<"[";
    for(i=0,c=T[u].l;c!=NIL;i++,c=T[c].r){
        if(i)cout<<", ";
        cout<<c;
    }
    cout<<"]"<<endl;
}
//递归地求深度
int rec(int u,int p){
    D[u]=p;
    if(T[u].r!=NIL)rec(T[u].r,p);//右侧兄弟设置为相同深度
    if(T[u].l!=NIL)rec(T[u].l,p+1);//最左侧子节点的深度设置为自己的深度+1
}
int main(){
    int i,j,d,v,c,l,r;
    cin>>n;
    for(i=0;i<=n;i++)T[i].p=T[i].l=T[i].r=NIL;
    for(i=0;i<n;i++){
        cin>>v>>d;
        for(j=0;j<d;j++){
            cin>>c;
            if(j==0)T[v].l=c;
            else T[l].r=c;
            l=c;
            T[c].p=v;
        }
    }
    for(i=0;i<n;i++){
        if(T[i].p==NIL)r=i;
    }
    rec(r,0);
    for(i=0;i<n;i++)print(i);
    return 0;
}
原书代码中,对初学者,比较难理解的地方是:左子右兄表示法。笔者解释如下,左子关系表示父子,右子关系表示兄弟。

原书样例,画图如下:


上图,左子右兄表示法 图如下:


左子右兄表示法 优点,个人体会是,能轻易的将一棵树 转化为 二叉树

仿照上述代码,本人编写的C语言AC代码如下:

#include <stdio.h>
#include <string.h>
struct node{
    int p,l,r;
}T[100100];
int n,D[100100];//深度
void dfs(int u,int d){
    D[u]=d;
    if(T[u].l!=-1)dfs(T[u].l,d+1);
    if(T[u].r!=-1)dfs(T[u].r,d);
}
void print(){
    int i,j,c;
    for(i=0;i<n;i++){
        printf("node %d: parent = %d, depth = %d,",i,T[i].p,D[i]);
        if(T[i].p==-1)printf(" root, ");
        else if(T[i].l==-1)printf(" leaf, ");
        else printf(" internal node, ");
        printf("[");
        for(j=0,c=T[i].l;c!=-1;j++,c=T[c].r){
            if(j)printf(", ");
            printf("%d",c);
        }
        printf("]\n");
    }
}
int main(){
    int r,c,u,k,i,j,p;
    memset(T,-1,sizeof(T));
    scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d%d",&u,&k);
        for(j=0;j<k;j++){
            scanf("%d",&c);
            if(j==0)T[u].l=c;
            else T[r].r=c;
            r=c;
            T[c].p=u;
        }
    }
    for(i=0;i<n;i++)
        if(T[i].p==-1){
            p=i;
            break;
        }
    dfs(p,0);
    print();
    return 0;
}
2017-9-20 22:16

8.3 ALDS1_7_B Binary Trees

原书AC代码:

//ALDS1_7_B:Binary Trees
#include <cstdio>
#define MAX 10000
#define NIL -1
struct Node{int parent,left,right;};
Node T[MAX];
int n,D[MAX],H[MAX];
void setDepth(int u,int d){
    if(u==NIL)return;
    D[u]=d;
    setDepth(T[u].left,d+1);
    setDepth(T[u].right,d+1);
}
int setHeight(int u){
    int h1=0,h2=0;
    if(T[u].left!=NIL)
        h1=setHeight(T[u].left)+1;
    if(T[u].right!=NIL)
        h2=setHeight(T[u].right)+1;
    return H[u]=(h1>h2?h1:h2);
}
//返回结点u的兄弟结点
int getSibling(int u){
    if(T[u].parent==NIL)return NIL;
    if(T[T[u].parent].left!=u&&T[T[u].parent].left!=NIL)
        return T[T[u].parent].left;
    if(T[T[u].parent].right!=u&&T[T[u].parent].right!=NIL)
        return T[T[u].parent].right;
    return NIL;
}
void print(int u){
    printf("node %d: ",u);
    printf("parent = %d, ",T[u].parent);
    printf("sibling = %d, ",getSibling(u));
    int deg=0;
    if(T[u].left!=NIL)deg++;
    if(T[u].right!=NIL)deg++;
    printf("degree = %d, ",deg);
    printf("depth = %d, ",D[u]);
    printf("height = %d, ",H[u]);
    if(T[u].parent==NIL){
        printf("root\n");
    }else if(T[u].left==NIL&&T[u].right==NIL){
        printf("leaf\n");
    }else{
        printf("internal node\n");
    }
}
int main(){
    int v,l,r,root=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)T[i].parent=NIL;
    for(int i=0;i<n;i++){
        scanf("%d %d %d",&v,&l,&r);
        T[v].left=l;
        T[v].right=r;
        if(l!=NIL)T[l].parent=v;
        if(r!=NIL)T[r].parent=v;
    }
    for(int i=0;i<n;i++)if(T[i].parent==NIL)root=i;
    setDepth(root,0);
    setHeight(root);
    for(int i=0;i<n;i++)print(i);
    return 0;
}
仿照上述代码,本人编写的C语言AC代码如下:

//ALDS1_7_B Binary Trees
#include <stdio.h>
#include <string.h>
struct node{
    int parent,left,right;
}T[30];
int H[30],D[30];//H[]高度 D[]深度
int setHeight(int u){
    int h1=0,h2=0;//2此处写成 int h1,h2;
    if(T[u].left!=-1)
        h1=setHeight(T[u].left)+1;
    if(T[u].right!=-1)
        h2=setHeight(T[u].right)+1;//1此处写成 h2=setHeight(T[u].right+1);
    return H[u]=h1>h2?h1:h2;
}
void setDepth(int u,int d){
    D[u]=d;
    if(T[u].left!=-1)setDepth(T[u].left,d+1);
    if(T[u].right!=-1)setDepth(T[u].right,d+1);
}
void print(int u){
    int deg=0;
    printf("node %d: parent = %d, ",u,T[u].parent);
    printf("sibling = ");
    if(T[u].parent==-1)printf("-1, ");//4 添上改行 就因为少了该句,调试程序1个小时
    else if(T[T[u].parent].left!=-1&&T[T[u].parent].left!=u)
        printf("%d, ",T[T[u].parent].left);
    else if(T[T[u].parent].right!=-1&&T[T[u].parent].right!=u)
        printf("%d, ",T[T[u].parent].right);
    else
        printf("-1, ");
    if(T[u].left!=-1)deg++;
    if(T[u].right!=-1)deg++;
    printf("degree = %d, ",deg);
    printf("depth = %d, ",D[u]);
    printf("height = %d, ",H[u]);
    if(T[u].parent==-1)printf("root\n");
    else if(T[u].left==-1&&T[u].right==-1)printf("leaf\n");
    else printf("internal node\n");
}
int main(){
    int n,i,root=0,v,l,r;
    memset(T,-1,sizeof(T));
    scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d%d%d",&v,&l,&r);
        if(l!=-1){T[v].left=l,T[l].parent=v;}
        if(r!=-1){T[v].right=r,T[r].parent=v;}
    }
    for(i=0;i<n;i++)
        if(T[i].parent==-1){
            root=i;
            break;
        }
    setHeight(root);
    setDepth(root,0);
    for(i=0;i<n;i++)
        print(i);
    return 0;
}
原书程序问题,数组开得太大,题目中约束0<=n<=25。

2017-9-26 23:08 AC该问题

8.4 ALDS1_7_C:Tree Walk

原书AC代码:

//ALDS1_7_C:Tree Walk
#include <stdio.h>
#define MAX 10000
#define NIL -1
struct Node{int p,l,r;};
struct Node T[MAX];
int n;
/*前序遍历*/
void preParse(int u){
    if(u==NIL)return;
    printf(" %d",u);
    preParse(T[u].l);
    preParse(T[u].r);
}
/*中序遍历*/
void inParse(int u){
    if(u==NIL)return;
    inParse(T[u].l);
    printf(" %d",u);
    inParse(T[u].r);
}
/*后序遍历*/
void postParse(int u){
    if(u==NIL)return;
    postParse(T[u].l);
    postParse(T[u].r);
    printf(" %d",u);
}
int main(){
    int i,v,l,r,root;
    scanf("%d",&n);
    for(i=0;i<n;i++){
        T[i].p=NIL;
    }
    for(i=0;i<n;i++){
        scanf("%d %d %d",&v,&l,&r);
        T[v].l=l;
        T[v].r=r;
        if(l!=NIL)T[l].p=v;
        if(r!=NIL)T[r].p=v;
    }
    for(i=0;i<n;i++)if(T[i].p==NIL)root=i;
    printf("Preorder\n");
    preParse(root);
    printf("\n");
    printf("Inorder\n");
    inParse(root);
    printf("\n");
    printf("Postorder\n");
    postParse(root);
    printf("\n");
    return 0;
}

仿照上述代码,本人编写的C语言AC代码如下:

//ALDS1_7_C:Tree Walk
#include <stdio.h>
#include <string.h>
struct node{
    int parent,left,right;
}T[30];
void Preorder(int u){//先序遍历
    if(u==-1)return;//u==-1叶子节点的下一个节点
    printf(" %d",u);//根
    Preorder(T[u].left);//左
    Preorder(T[u].right);//右
}
void Inorder(int u){//中序遍历
    if(u==-1)return;
    Inorder(T[u].left);//左
    printf(" %d",u);//根
    Inorder(T[u].right);//右
}
void Postorder(int u){//后序遍历
    if(u==-1)return;
    Postorder(T[u].left);//左
    Postorder(T[u].right);//右
    printf(" %d",u); //根
}
int main(){
    int n,i,root=0,v,l,r;
    memset(T,-1,sizeof(T));
    scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d%d%d",&v,&l,&r);
        if(l!=-1){
            T[v].left=l,T[l].parent=v;
        }
        if(r!=-1){
            T[v].right=r,T[r].parent=r;
        }
    }
    for(i=0;i<n;i++)
        if(T[i].parent==-1){
            root=i;
            break;
        }
    printf("Preorder\n");
    Preorder(root);
    printf("\n");
    printf("Inorder\n");
    Inorder(root);
    printf("\n");
    printf("Postorder\n");
    Postorder(root);
    printf("\n");
    return 0;
}
收获,学习了一种二叉树的输入输出方式。
2017-9-27

8.5 ALDS1_7_D:Reconstruction of the Tree

上在线测评网站,发现该题名字应为:ALDS1_7_D:Reconstruction of a Tree

提交,程序一直处于:Judging状态,估计AOJ此题处于修改,或删除状态。

原书样例通过的代码:

//ALDS1_7_D:Reconstruction of the Tree
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
int n,pos;
vector<int> pre,in,post;
void rec(int l,int r){
    if(l>=r)return;
    int root=pre[pos++];
    int m = distance(in.begin(),find(in.begin(),in.end(),root));
    rec(l,m);
    rec(m+1,r);
    post.push_back(root);
}
void solve(){
    pos = 0;
    rec(0,pre.size());
    for(int i=0;i<n;i++){
        if(i)cout<<" ";
        cout<<post[i];
    }
    cout<<endl;
}
int main(){
    int k;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>k;
        pre.push_back(k);
    }
    for(int i=0;i<n;i++){
        cin>>k;
        in.push_back(k);
    }
    solve();
    return 0;
}

仿照上述代码,本人编写的C语言样例通过代码如下:

//ALDS1_7_D:Reconstruction of the Tree
#include <stdio.h>
int pre[110],in[110],post[110],pos=1,k=1,n;
void rec(int left,int right){//用中序,先序构建后序
    int c,i;//根
    if(left>right)return;
    c=pre[pos++];
    for(i=1;i<=n;i++)
        if(in[i]==c){
            break;
        }
    rec(left,i-1);
    rec(i+1,right);
    post[k++]=c;
}
int main(){
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&pre[i]);
    for(i=1;i<=n;i++)
        scanf("%d",&in[i]);
    rec(1,n);
    for(i=1;i<=n;i++)
        printf("%d ",post[i]);
    return 0;
}

通过该题,深刻认识到,先,中,后 序的核心在于 根,根是三种转换的桥梁。

2017-9-27 19:08样例通过。


2017-9-27 19:09完成该章内容学习,二叉树知识得到巩固,递归技能得到加强,明白了根是二叉树的核心,掌握了树的左子右兄表示法。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值