PTA(二叉树的同构+List Leaves+Tree Traversals Again)

二叉树的同构//题目链接

此题一大坑点就是数据的读入......反正我是用scanf读入时debug很久最后被迫换了cin才解决的。

剩下的就是逻辑分析 详细情况请看代码注释

#include<bits/stdc++.h>
using namespace std;
typedef struct Btree tree;
#define  noil -1
#define maxsize 12
#define  ElementType int
#define type char
struct Btree{

    type data;
    ElementType left;
    ElementType right;

}Tree1[maxsize],Tree2[maxsize];

int create_tree(tree Tree[]);
bool judge(int r1,int r2);
bool check[maxsize];
int main()
{

    int r1=create_tree(Tree1);
    int r2=create_tree(Tree2);
    judge(r1,r2)?cout<<"Yes\n":cout<<"No\n";
    return 0;
}
int create_tree(tree Tree[])
{
    int n;
    cin>>n;
    if(!n)
        return noil;

    char CL,CR;
    memset(check,false,sizeof(check));

    for(int i=0;i<n;i++)
    {
        cin>>Tree[i].data>>CL>>CR;

        if(CL!='-')
        {
            Tree[i].left=CL-'0';
            check[Tree[i].left]=true;
        }
        else
            Tree[i].left=noil;

        if(CR!='-')
        {
            Tree[i].right=CR-'0';
            check[Tree[i].right]=true;
        }
        else
            Tree[i].right=noil;
    }

    for(int i=0;i<n;i++)//寻找根结点的标志数组。
        if(!check[i])
            return i;


}
bool judge(int r1,int r2)
{
    if(r1==noil&&r2==noil)//根结点为空 即为空树或遍历到叶子结点时
        return true;
    if((r1==noil&&r2!=noil)||(r1!=noil&&r2==noil)) //一个空 另一个不空 必定不相等
        return false;
    if(Tree1[r1].data!=Tree2[r2].data)//当前两结点元素不相等
        return false;
    if(Tree1[r1].left==noil&&Tree2[r2].left==noil) //左边同时为空,判断右边即可
        return judge(Tree1[r1].right,Tree2[r2].right);

    if(Tree1[Tree1[r1].left].data==Tree2[Tree2[r2].left].data) //左结点同时相等,且不为空,再同时判断右结点。

       return  judge(Tree1[r1].right,Tree2[r2].right);

    if(Tree1[Tree1[r1].left].data!=Tree2[Tree2[r2].left].data) //左边不相等时,互换左右结点顺序
      
       return   (judge(Tree1[r1].left,Tree2[r2].right)&&
                 judge(Tree1[r1].right,Tree2[r2].left));

}

List Leaves//题目链接

此题大致意思是按层遍历,并按遍历到的先后顺序输出叶子结点。

思路是按层遍历时需要用到一个队列来进行存储当前结点的左右孩子,然后再判断是否为叶子节点,一个重点是如何找到根节点......................其实思路就是遍历一遍所输入的结点,并从1—N中查找为出现的元素即为根节点,用一个check数组来记录是否出现。

#include<bits/stdc++.h>
using namespace std;
typedef struct Btree tree;
#define maxsize 12
#define  ElementType char
#define noil -1
struct Btree{

    ElementType left;
    ElementType right;

}Tree1[maxsize];

int create_tree(tree Tree[]);
int n;
bool check[maxsize];//标记用来寻找根节点
void deal(int rt);

int main()
{

    int rt=create_tree(Tree1);
    deal(rt);

    return 0;
}
int create_tree(tree Tree[])//建树并返回根节点
{
    cin>>n;
    if(!n)//若为0,则为空树
        return noil;

    for(int i=0;i<n;i++)
    {
        cin>>Tree[i].left>>Tree[i].right;

        if(Tree[i].left!='-')//判断左右孩子是否为空
            check[Tree[i].left-'0']=true;
        if(Tree[i].right!='-')
            check[Tree[i].right-'0']=true;

    }

    for(int i=0;i<n;i++)
        if(!check[i])
            return i;
}
void deal(int rt)
{
    if(rt==noil)
    {
        cout<<0<<endl;
        return;
    }
    queue<int> p;

    int index,ans[maxsize],cnt=0;
    p.push(rt);

    while(!p.empty())
    {

        index=p.front();
        p.pop();
        if(Tree1[index].left=='-'&&Tree1[index].right=='-')
        {
            ans[cnt++]=index;//记录叶子结点的值
        }

        else if(Tree1[index].left!='-')//分别将当前结点的左右孩子入队
        {
            int e=Tree1[index].left-'0';
            p.push(e);
        }
        if(Tree1[index].right!='-')
        {
            int e=Tree1[index].right-'0';
            p.push(e);
        }


    }
    for(int i=0;i<cnt;i++)
    {
        cout<<ans[i];
        if(i!=cnt-1)
            cout<<" ";
    }

}

Tree Traversals Again//题目链接

此题的大致意思是用非递归的方式建立(遍历)一棵树,再输出其后序遍历的结果。

思路为借住堆栈,根据所给输出进行判断,若为Push,则将当前结点入栈,若为Pop,则弹出一个元素,并且下次Push时的元素应为弹出结点的右孩子。

如1,2,3,分别入栈,3的左孩子为空,则弹出3,由于题目描述连续两次Pop,所以继续弹出2,下次Push的元素应为2的右孩子,即为4.

#include<bits/stdc++.h>
using namespace std;
typedef struct Btree tree;
#define maxsize 50
#define  ElementType int
#define noil -1
struct Btree{

    ElementType left;
    ElementType right;
    ElementType data;

}Tree[maxsize];
int n,rt;
int pre_deal();
void Print(int index);
int main()
{

    int root=pre_deal();
    Print(root);

    return 0;
}
int pre_deal()
{
    scanf("%d",&n);
    stack<int> p;
    int num,tmp;
    char op[5],index[5];/*index为当每次输入字符串的上次记录,
                        用来判断当前元素是否位于当前结点的右孩子*/

    scanf("%s%d",&op,&tmp);//预处理第一个结点
    p.push(tmp);
    Tree[tmp].data=tmp;
    rt=tmp;
    strcpy(index,op);
    Tree[tmp].left=noil;
    Tree[tmp].right=noil;

    for(int i=0;i<(n<<1)-1;i++)
    {
        scanf("%s",&op);

        if(!strcmp(op,"Push"))
        {
            scanf("%d",&num);
            Tree[num].left=noil;//每次先初始化即将入栈结点的左右孩子为空。
            Tree[num].right=noil;

            if(!strcmp(index,"Push"))

                Tree[tmp].left=num;
            else
                Tree[tmp].right=num;

            Tree[num].data=num;
            tmp=num;
            p.push(num);
            strcpy(index,op);

        }
        if(!strcmp(op,"Pop"))
        {
            tmp=p.top();
            p.pop();
            strcpy(index,op);

        }

    }

    return rt;返回该树的根节点

}
void Print(int index)//采用递归进行遍历
{
    if(index!=noil)
    {
        Print(Tree[index].left);
        Print(Tree[index].right);
        printf("%d",Tree[index].data);
        if(Tree[index].data!=rt)
            printf(" ");
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值