中国大学MOOC浙大数据结构PTA课后题

在这里占个坑,记录一下学习数据结构中例题

目录

二叉树的同构

 1.建树

 2.判断是否为同构

3.同类型题目

是否同一棵二叉搜索树

思路

代码



二叉树的同构

题目:题目详情 - 03-树1 树的同构 (25 分) (pintia.cn)https://pintia.cn/problem-sets/1497448825169559552/problems/1503334324290916352

 1.建树

首先理清题目意思,给出的每组数据中,仅仅表现了父节点的内容与子节点的编号的关系,无法确定根节点。

这里用结构体数组来储存树,根据数组的下标,则可确定当前节点的内容与孩子节点的位置。找到根节点的位置后,整棵树的架构便明确下来。

根节点的特殊之处在于,根节点是是无人指向的。

为了找出根节点,可以使用一个初值全为0的数组,若数组下标被指向,则反转为1。

 2.判断是否为同构

设置一个递归函数(目的:判断两树是否同构),传入两棵树。

同构操作的实质是什么?我认为是交换左右子树。镜像对称的两树是同构的特殊情况,而同构是从上到下,逐渐深入,每次交换(或不交换)左右子树。

分情况进行递归的选择:

两树都为空:则一定是同构的。

只有一个是空的,或者根节点的元素不一样,一定不同构。

两个左子树都为空,则判断两右子树是否同构。(这里的左右不必纠结,也没有特殊性)

接下来判断根节点的左右节点,若左等于左,右等于右,则说明在这一步是相同的,接下来进行的操作是传入递归,比较分别比较两个左子树、两个右子树是否同构。若在根节点那一步,发生了左右交换,则比较左树的右子树和有树的左子树、左数的左和右数的右是否同构。

代码:

#include <iostream>
using namespace std;
#define maxsize 11
#define Null -1
typedef int Tree;
struct TNode {
    char data;
    Tree left,right;
}T1[maxsize], T2[maxsize];
Tree BuildTree(struct TNode T[]){
    int N,root;
    char l,r;
    bool isroot[maxsize];
    root = Null;
    scanf("%d", &N);
    if(N) {
        for(int i = 0; i < N; ++i) isroot[i] = true;
        getchar();
        for(int i = 0; i < N; ++i) {
            scanf("%c %c %c", &T[i].data, &l, &r);
            getchar();
            if(l != '-') {
                T[i].left = l -'0';
                isroot[T[i].left] = false;
            } else T[i].left = Null;
            if(r != '-') {
                T[i].right = r -'0';
                isroot[T[i].right] = false;
            } else T[i].right = Null;
        }
        for(int i = 0; i < N; ++i) 
            if(isroot[i]) {
                root = i;
                break;
            }
    }
    return root;
}
bool judge(Tree R1, Tree R2) {
    if(R1 == Null && R2 == Null)    
        return true;    //两个都为空
    if((R1 == Null && R2 != Null) || (R1 != Null && R2 == Null))
        return false;   //其中一个为空
    if(T1[R1].data != T2[R2].data)
        return false;   //根节点元素就不一样
    //两个左子树都为空,则判断右子树是否同构
    if(T1[R1].left == Null && T2[R2].left == Null) 
        return judge(T1[R1].right, T2[R2].right);
    //两个左子树都不为空且元素相同,不用交换
    if((T1[R1].left != Null) && (T2[R2].left != Null) 
            && (T1[T1[R1].left].data == T2[T2[R2].left].data))
        return judge(T1[R1].left, T2[R2].left) && 
            judge(T1[R1].right, T2[R2].right);
    else {//交换左右子树,判断
        return judge(T1[R1].left, T2[R2].right) && 
               judge(T1[R1].right, T2[R2].left);
    }
}
int main() {
    Tree R1, R2;
    R1 = BuildTree(T1);
    R2 = BuildTree(T2);
    if(judge(R1, R2)) 
        cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}

3.同类型题目

PTA | 程序设计类实验辅助教学平台千名教师建设,万道高质量题目,百万用户拼题的程序设计实验辅助教学平台https://pintia.cn/problem-sets/1497448825169559552

层次遍历——使用队列实现

首先根节点入队,执行循环

{

pop队列中队头的元素

判断此元素左右孩子是否为空,将其不空的左右孩子入队

}

是否同一棵二叉搜索树

题目详情 - 04-树4 是否同一棵二叉搜索树 (25 分) (pintia.cn)https://pintia.cn/problem-sets/1497448825169559552/problems/1505905647748263937

思路

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。

这里采取的方法是先根据第一行的输入建立一棵树T,再判断序列与树是否同源。

首先在书中寻找序列的某个元素,看寻找的路径中,是否有新出现的节点。(也就是说这个序列中,如果不事先知道这个节点的值的话,是不可能得到像T一般的树的)

因此需要设置标志,判断是否已经访问过了。

代码

#include <iostream>
using namespace std;
#define maxsize 11
typedef struct TNode* Tree;
struct TNode {
    int data;
    Tree left,right;
    int flag;   //判断是否访问过
};

void Clear(Tree R) {    //清除标记
    if(!R) return;
    R->flag = 0;
    Clear(R->left);
    Clear(R->right);
}
void FreeTree(Tree R) { //清空该树
    if(!R) return;
    FreeTree(R->left);
    FreeTree(R->right);
    delete R;
}
Tree NewNode(int data) {//
    Tree R = new TNode;
    R->data = data;
    R->left = R->right = NULL;
    R->flag = 0;
    return R;
}
Tree BST_Insert(int data, Tree R) {
    if (!R) R = NewNode(data);
    else {
        if(data > R->data)  //大于该结点,插入到右子树
            R->right = BST_Insert(data, R->right);
        else                //小于或等于该结点,插入到左子树
            R->left = BST_Insert(data, R->left);
    }
    return R;
}
Tree Build(int N) {
    Tree R = NULL;
    int x;
    cin >> x;
    R = NewNode(x);
    for(int i = 1; i < N; ++i) {
        cin >> x;
        R = BST_Insert(x, R);
    }
    return R;
}
bool check(int data, Tree R) {
    if(R->flag) {//已经访问过了
        if(data < R->data) 
            return check(data, R->left);
        else if(data > R->data) 
            return check(data, R->right);
        else return false;
    } else {
        if(data == R->data) {
            R->flag = 1;
            return true;
        } else return false;
    }
}
bool judge(Tree R1, int N) {
    int x;
    bool flag = true;
    if(N && R1) {
        cin >> x;
        if(x != R1->data) flag = false;
        R1->flag = 1;
        for(int i = 1; i < N; ++i) {
            cin >> x;
            if(flag && (!check(x,R1))) flag = false;
        }
    }
    return flag;
}
int main() {    
    int N, L;
    cin >> N;
    while(N) {
        cin >> L;
        Tree R1;
        R1 = Build(N);
        for(int i = 0; i < L; ++i) {
            if(judge(R1, N)) 
                cout << "Yes" << endl;
            else cout << "No" << endl;
            Clear(R1);  //清除标记
        }   
        FreeTree(R1);
        cin >> N;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值