浙大数据结构第三周之03-树1 树的同构

news2024/11/26 22:22:25

题目详情:

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

图1

图2

现给定两棵树,请你判断它们是否是同构的。

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图1):

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -

输出样例1:

Yes

输入样例2(对应图2):

8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:

No

主要思路:

先要理解这句话:对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点

这句话的意思是:第i行节点编号是i,但建树时可不一定按0~n-1从左到右从上到下来建,而要根据节点关系来

难点主要分为两大部分:

(一)建树:

用一个大数组来建树,大数组的下标i对应节点i,在过程中找到根节点,扫描树时利用根节点先序遍历

(1)先初始化大数组,将每个节点存储的character设置为EMPTY,状态设置为true

(2)再遍历输入,其中处理后面子节点有讲究,应该先按字符读取,然后再判断,如果是数字,就改为数字后存入节点,否则说明子节点为空,并将子节点状态定义为false

(3)遍历大数组,其中节点character不为EMPTY且状态不为false的就是根节点

(二)判断是不是同构,用到前序遍历、递归三部曲:

(1)参数和返回值

参数:两棵树各自根节点;返回值:以当前根节点是否满足题意

(2)结束条件:

遍历到空节点

(3)遍历顺序:

前序遍历,其中的单层递归逻辑:先判断当前两个根节点是否相等,再看各自左孩子与各自右孩子是否相等,如果相等直接分别递归,如果不相等,就将第一棵子树左孩子传入下一层递归与第二棵子树右孩子比较;第一棵子树右孩子传入下一层递归与第二棵子树左孩子比较

第一次写错误:

(1)这道题有一个非常细节的点,就是如何定义表示空节点的常量NONE,当读入的符号是‘-’时,说明是空节点,如果将NONE定义为-1,那么当-1是不能用数组表示的,因为数组下标从0开始,所以因为本题数据不大(小于10),所以将最大数据MAX_SIZE定义为15,NONE定义为14(还不理解可以看代码里注释)

(2)树可能是空数,判断时要额外加一条

代码实现:

#include <stdio.h>
#include <stdbool.h>
#define MAX_SIZE 15
#define EMPTY '-'
#define NONE 14
/*定义树的数据结构*/
typedef struct TreeNode Tree;
struct TreeNode {
    char Character;
    int LeftChild;
    int RightChild;
    bool IsRoot;
};
/*建树*/
int BuildTree(int nodeNum, Tree* tree) {
    for(int i = 0; i < nodeNum; i++) {  //首先初始化树的结构体数组
        tree[i].Character = EMPTY;
        tree[i].IsRoot = true;
    }
    for(int i = 0; i < nodeNum; i++) {  //读入树的结构体数组
        char charLeftChild, charRightChild;
        scanf("%c %c %c", &(tree[i].Character), &charLeftChild, &charRightChild);
        getchar();  //读取换行符
        if(charLeftChild >= '0' && charLeftChild <= '9') {
            tree[i].LeftChild = charLeftChild - '0';
            tree[tree[i].LeftChild].IsRoot = false;
        }
        else if(charLeftChild == EMPTY) {
            tree[i].LeftChild = NONE;    //建树的这里很关键,因为树如果将NONE定义为-1,则下面tree[i].LeftChild就是-1,数组是没有-1的下标的
            tree[tree[i].LeftChild].Character = EMPTY;    //一定要有这步,因为这样在下面判断递归时才可以判断空节点(理解不了就debug)
        }
        if(charRightChild >= '0' && charRightChild <= '9') {
            tree[i].RightChild = charRightChild - '0';
            tree[tree[i].RightChild].IsRoot = false;
        }
        else if(charRightChild == EMPTY) {
            tree[i].RightChild = NONE;
            tree[tree[i].RightChild].Character = EMPTY;
        }
    }
    int rootId = -1;
    for(int i = 0; i < nodeNum; i++) {
        if(tree[i].Character != EMPTY && tree[i].IsRoot == true) {
            rootId = i;
            break;
        }
    }
    return rootId;
}
/*通过前序遍历判断是否同构*/
bool Judge(Tree* tree1, int root1, Tree* tree2, int root2) {
    //终止条件:遍历到空节点
            if(root1 == NONE && root2 == NONE) {  //两个都为空,返回true
        return true;
    }
    if((root1 == NONE && root2 != NONE) || (root1 != NONE && root2 == NONE)) {  //两个都不为空,返回false
        return false;
    }

    //前序遍历
    if(tree1[root1].Character == tree2[root2].Character) {  //如果根节点相同
        bool leftSubTree;
        bool rightSubTree;
        if(tree1[tree1[root1].LeftChild].Character == tree2[tree2[root2].LeftChild].Character &&  //左右子树对应相同
           tree1[tree1[root1].RightChild].Character == tree2[tree2[root2].RightChild].Character) {
                leftSubTree = Judge(tree1, tree1[root1].LeftChild, tree2, tree2[root2].LeftChild);
                rightSubTree = Judge(tree1, tree1[root1].RightChild, tree2, tree2[root2].RightChild);
                if(leftSubTree && rightSubTree) {
                    return true;
                }
                else return false;
        }    
        else {  //如果左右子树对应不同,就看1的左子树与2的右子树是否相同
            leftSubTree = Judge(tree1, tree1[root1].RightChild,
                                tree2, tree2[root2].LeftChild);
            rightSubTree = Judge(tree1, tree1[root1].LeftChild,
                                 tree2, tree2[root2].RightChild);
            if(leftSubTree && rightSubTree) return true;
            else return false;
        }
    }
    else return false;  //如果根节点不同不用看了,直接false
}

int main() {
    //建第一棵树
    int treeNode1;
    scanf("%d", &treeNode1);
    getchar();
    Tree tree1[MAX_SIZE];
    int root1 = BuildTree(treeNode1, tree1);

    //建第二棵树
    int treeNode2;
    scanf("%d", &treeNode2);
    getchar();
    Tree tree2[MAX_SIZE];
    int root2 = BuildTree(treeNode2, tree2);

    if(Judge(tree1, root1, tree2, root2) && treeNode1 >= 1 && treeNode2 >= 1) {
        printf("Yes");
    }
    else if(treeNode1 == 0 && treeNode2 == 0) {
        printf("Yes");
    }
    else printf("No");
    
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/750028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python物联网开发-Python_Socket通信开发-Python与Tcp协议物联网设备通信-Socket客户端

一、前言 Python在物联网开发中的重要愈来愈重&#xff0c;因此&#xff0c;掌握Python语言与物联网设备之间的通信就显得尤为重要&#xff0c;可以通过编写Python程序实现获取物联网设备的传感器数值并可以更改物联网设备上的执行器状态。 二、程序实现 首先&#xff0c;当使…

中位数(树状数组+二分)

L-中位数_2023河南萌新联赛第&#xff08;一&#xff09;场&#xff1a;河南农业大学 (nowcoder.com) 树状数组二分 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N2e6; const long long inf 0x7f7f7f7f7f7f7f7f; #define endl \n in…

【Android Framework系列】第5章 AMS启动流程

1 AMS简介 AMS&#xff08;Activity Manager Service&#xff09;是Android中最核心的服务&#xff0c;管理着四大组件的启动、切换、调度及应用进程的管理和调度等工作。AndroidQ将Activity移到了ActivityTaskManagerService中&#xff0c;但也和AMS相关联。 AMS通过使用一些…

【来不及刷题之】44、滑动窗口最小值

暴力方法&#xff1a;超时 class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int nnums.length;int sizen-(k-1);int[] resnew int[size];int slow0,quickk-1;int maxNumfindMax(nums,slow,quick);res[0]maxNum;while (quick<n-1){quick;int addNumnums…

66. 两个链表的第一个公共结点

目录 链接&#xff1a; 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 图片&#xff1a; 链接&#xff1a; 原题链接 题目&#xff1a; 输入两个链表&#xff0c;找出它们的第一个公共结点。 当不存在公共节点时&#xff0c;返回空节点。 数据范围 链表长度 [1,200…

mapbox跳过accesstoken检测

不写token的时候&#xff0c;控制台就会报这个错 写上token的时候&#xff0c;就会报这个错 然后想让这个错不再出现&#xff0c;就不要再声明mapboxgl.accessToken&#xff0c;并且把node_mudules这个文件夹下面的这个文件里面的红圈内的括号内容改成false。 this._request…

React 安装 报错“Modal不能用作jsx组件”

提示 &#xff1a;‘Modal’ cannot be used as a JSX component. 原因&#xff1a;可能导致是类似antd组件报错 要确认react ts 版本是否适配 解决方法&#xff1a; 第一步&#xff1a;查看代码中的 package.json 文件 查看 typescript 与 types/react 第二步&#xff1a;查…

这些ai图片处理工具就是你神奇的创作伙伴

当我们需要图像来代表某种概念或主题时&#xff0c;我们通常需要花费大量的时间去寻找、编辑、或者设计一张符合要求的图片。但是现在&#xff0c;随着人工智能技术的发展&#xff0c;越来越多的ai自动生成图片软件被开发出来&#xff0c;让我们可以更快捷地获取所需的图像。那…

【Flutter】 Flutter 实现 List Sort 排序 解决复杂业务逻辑下的数据排序问题

文章目录 一、前言二、Flutter 中的 List 排序基础1. Flutter 中的 List 简介2. List 的基本排序方法3. 自定义排序规则 三、在 Flutter 中实现复杂业务逻辑的 List 排序1. 业务逻辑一&#xff1a;根据对象属性排序2. 业务逻辑二&#xff1a;多条件排序 四、完整的 Flutter Lis…

pythonocc进阶学习:faces的inner wire与outer wire

总目录 >> PythonOCC入门进阶到实战(目前已更新入门篇、基础篇和进阶篇) 我们在这篇文章中绘制了带有holes的面&#xff0c; 本篇是在读取到外部文件如brep&#xff0c;igs&#xff0c;stp后获取面的性质&#xff0c;寻找面中的wires的正向与逆向 只显示外wire from O…

TCP/IP参考模型之http协议分层,三次握手、四次挥手

三次握手和四次挥手的过程&#xff1a; 三次握手&#xff1a; TCP建立连接的过程我们称之为3次握手。 &#xff08;1&#xff09;第一次握手 PC1使用一个随机的端口号向PC2的80端口发送连接请求&#xff0c;此过程的典型标志为SYN控制位为1&#xff0c;其他五位为0。 &#x…

credal set 的一些熵

今天看论文的时候看到credal set 的upper entropy [1]&#xff0c;另外作者还给出了一些这个熵的优点。 当然在[2] 里面又变成了缺点。 注意在上一篇博文&#xff0c;credal decision tree的论文里面&#xff0c;作者又推翻了自己的观点&#xff0c;认为这个熵是disaggregat…

C++数据结构笔记(9)树与二叉树的基本概念

1.只有一个结点也可以称为树&#xff0c;只不过没有叶子结点&#xff1b;也可以有0个结点&#xff0c;称为空树。 2.树具有递归性&#xff0c;树中还有树 3.结点的度&#xff1a;结点所拥有的子树的个数 4.树的高度&#xff1a;树的子树的最高层数 5.树的广义表示法&#x…

多肽合成定制756500-22-8,cyclo(Arg-Gly-Asp-d-Phe-Glu),试剂信息说明

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 英文名称&#xff1a;cyclo(Arg-Gly-Asp-d-Phe-Glu) 规格标准&#xff1a;1g、5g、10g CAS&#xff1a;756500-22-8 分子式&#xff1a;C26H36N8O9 分子量&#xff1a;604.61 ------cyclo(Arg-Gly-Asp-d-Phe-Glu)结构式-…

AuthenticationFailedException: 526 Authentication failure[0]的解决方案

0、一句话概括bug的原因 项目更换了邮箱服务器&#xff0c;原服务器支持的账号格式在新服务器上不被支持&#xff1b;即发送给新服务器的账号错误。 1、概述 &#xff08;1&#xff09;bug: java程序通知阿里云邮箱服务器发送邮件失败。 异常报错信息&#xff1a;Authentic…

如何在 Blender 中更快地渲染?这些技巧需要知道

Blender 是一款开源 3D 建模和动画软件&#xff0c;动画艺术家、产品设计师和游戏创作者经常使用。Blender 不仅允许用户创建 2D 对象或角色并对其进行动画处理以获得 3D 模型&#xff0c;而且 Blender 背后还有强大的艺术家和计算机科学家社区&#xff0c;不断改进代码以提供功…

基于javascript的可以自定义设置圆几等份的抽奖示例

基于javascript的可以自定义设置圆几等份的抽奖示例 效果示例图代码示例使用class 效果示例图 代码示例 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">* {padding…

声音合成——Foley Sound——DECASE项目——多模态智能感知与应用——论文复现(4)

文章目录 下载对应的代码attributeerror: adam object has no attribute get_updatesNameError: name _calculate_reconstruction_loss is not defined 下载对应的代码 论文下载链接安装tensorflow环境&#xff0c;这里需要一些前奏&#xff0c;比如说如何安装cuda&#xff0c…

【04golang中各种运算符优先级的讲解代码和注释】

在Golang中&#xff0c;不同的运算符具有不同的优先级&#xff0c;这会影响表达式的计算顺序。了解运算符的优先级是编写正确和可读性高的代码的关键。本文将对Golang中常见运算符的优先级进行讲解&#xff0c;并提供一些示例代码和注释。 以下是Golang中常见运算符的优先级从…