【编程题】7-3 树的同构

7-3 树的同构

  • 1 题目原文
  • 2 思路解析
  • 3 代码实现
  • 4 总结

1 题目原文

题目链接:7-3 树的同构

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

图1
fig1.jpg
图2
在这里插入图片描述

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

输入格式:

输入给出 2 2 2 棵二叉树的信息。对于每棵树,首先在一行中给出一个非负整数 n ( ≤ 10 ) n (≤10) n(10),即该树的结点数(此时假设结点从 0 0 0 n − 1 n−1 n1 编号);随后 n n n 行,第 i i i 行对应编号第 i i i 个结点,给出该结点中存储的 1 1 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

2 思路解析

    本题考查二叉树的相关知识。由题意可以了解到,二叉树的每个结点不是必须交换左右子树。判断二叉树是否同构在本质上是判断两棵二叉树是不是“相同”的,只是这个“相同”不是左子树和左子树“相同”,右子树和右子树“相同”,而是左子树可能和左子树“相同”,也可能和右子树“相同”,右子树同理。
    将上面的“相同”替换成“同构”,于是递归思路便呼之欲出,具体如下:
        1. 判断二叉树 A 和二叉树 B 是否同构;
        2. 若 A 是空树且 B 是空树,则同构;
        3. 若一棵树是空树但另一棵树不是空树,则不同构;
        4. 若两棵树都不是空树,则同构需满足:
            4.1 当前结点的值相同;
            4.2 当前 A 结点的左子树和 B 的右子树相同当前 A 结点的右子树和 B 的左子树相同当前 A 结点的左子树和 B 的左子树相同当前 A 结点的右子树和 B 的右子树相同。
    递归体现在 4.2 中。
    这道题的迭代思路和递归思路类似,甚至有点相当于将递归硬改成迭代了,意义不大,故不做记录。

3 代码实现

    需要注意的是,此题中给出的树是采用的“孩子表示法”表示的,但存储方式是顺序存储的,与一般的“二叉链表表示法”(链式存储)有所不同,这里将其“统一化”为二叉链表表示法,然后进行处理。

#include <stdio.h>
#include <stdlib.h>

// 二叉树结点定义
typedef struct TNode {
    char val;
    struct TNode *lc, *rc;
} TNode, Tree;

// 根据孩子表示法的数组构建二叉链表树
Tree *create_tree(char tree_arr[][3], int n, char null) {
    TNode *tn_arr[n];
    int i = 0, p[n];
    // 第一遍先创建所有结点并初始化“是否有父结点”的标志数组
    for (i = 0; i < n; i++) {
        tn_arr[i] = (TNode *)malloc(sizeof(TNode));
        tn_arr[i]->val = tree_arr[i][0];
        tn_arr[i]->lc = tn_arr[i]->rc = NULL;
        p[i] = 0;
    }
    // 第二遍将这些结点组合成树
    for (i = 0; i < n; i++) {
        if (tree_arr[i][1] != null) {
            tn_arr[i]->lc = tn_arr[tree_arr[i][1] - '0'];
            p[tree_arr[i][1] - '0'] = 1;
        }
        if (tree_arr[i][2] != null) {
            tn_arr[i]->rc = tn_arr[tree_arr[i][2] - '0'];
            p[tree_arr[i][2] - '0'] = 1;
        }
    }
    // 第三遍找出根结点并返回这棵树
    for (i = 0; i < n; i++) {
        if (!p[i]) return tn_arr[i];
    }
    return NULL;
}

// 判断两棵链式二叉树是否同构
int is_isomo(Tree *r1, Tree *r2) {
    // 两个都是空树,同构
    if (!r1 && !r2) return 1;
    // 一个是空树一个不是,不同构
    if (!r1 || !r2) return 0;
    // 两个都不是空树
    return r1->val == r2->val &&
           (is_isomo(r1->lc, r2->lc) && is_isomo(r1->rc, r2->rc) ||
            is_isomo(r1->lc, r2->rc) && is_isomo(r1->rc, r2->lc));
}

// 销毁二叉树
void destroy_tree(Tree *root) {
    if (!root) return;
    destroy_tree(root->lc);
    destroy_tree(root->rc);
    free(root);
}

int main(void) {
    // 读入数据
    int n = 0, m = 0, i = 0;
    scanf("%d", &n);
    char tree_a[n][3];
    for (i = 0; i < n; i++) {
        scanf(" %c %c %c", &tree_a[i][0], &tree_a[i][1], &tree_a[i][2]);
    }
    scanf("%d", &m);
    if (n ^ m) {
        printf("No\n");
        return 0;
    }
    char tree_b[m][3];
    for (i = 0; i < m; i++) {
        scanf(" %c %c %c", &tree_b[i][0], &tree_b[i][1], &tree_b[i][2]);
    }
    // 建树
    Tree *aa = create_tree(tree_a, n, '-');
    Tree *bb = create_tree(tree_b, m, '-');
    // 判断是否同构
    printf("%s\n", is_isomo(aa, bb) ? "Yes" : "No");
    // 销毁
    destroy_tree(aa);
    destroy_tree(bb);
    return 0;
}

4 总结

    判断二叉树的同构,其解决方法与判断二叉树是否相同类似,并且天然地可以使用递归的解法解决。关于树与二叉树的问题,如果可以用迭代解决的优先选择迭代,不过有时候迭代的思路并不好想,或者迭代的思路很复杂,那么使用递归解决就好。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WebP2P技术在嵌入式设备中的应用:EasyRTC音视频通话SDK如何实现高效通信?

在数字化时代&#xff0c;实时通信技术&#xff08;RTC&#xff09;与人工智能&#xff08;AI&#xff09;的融合正在重塑各个行业的交互方式。从在线教育到远程医疗&#xff0c;从社交娱乐到企业协作&#xff0c;RTC的应用场景不断拓展。然而&#xff0c;传统的RTC解决方案往往…

【前端】前端设计中的响应式设计详解

文章目录 前言一、响应式设计的定义与作用二、响应式设计的原则三、响应式设计的实现四、响应式设计的最佳实践总结 前言 在当今数字化时代&#xff0c;网站和应用程序需要适应各种设备&#xff0c;从桌面电脑到平板电脑和手机。响应式设计应运而生&#xff0c;成为一种可以适…

【AVRCP】探寻AVRCP控制互操作性:连接、命令与设备交互

AVRCP对于实现设备间的高效音频/视频控制至关重要。而控制互操作性要求作为AVRCP的核心部分&#xff0c;详细规定了设备在连接建立、命令传输等方面的具体操作。确保了不同设备之间能够实现无缝的远程控制。 一、AVCTP连接管理 1.1 AVCTP连接建立 发起者&#xff1a;AVCTP控制…

LLM大型语言模型(一)

1. 什么是 LLM&#xff1f; LLM&#xff08;大型语言模型&#xff09;是一种神经网络&#xff0c;专门用于理解、生成并对人类文本作出响应。这些模型是深度神经网络&#xff0c;通常训练于海量文本数据上&#xff0c;有时甚至覆盖了整个互联网的公开文本。 LLM 中的 “大” …

2025国家护网HVV高频面试题总结来了04(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 一、HVV行动面试题分类 根据面试题的内容&#xff0c;我们将其分为以下几类&#xff1a; 漏洞利用与攻击技术 …

解锁GPM 2.0「卡顿帧堆栈」|代码示例与实战分析

每个游戏开发者都有一个共同的愿望&#xff0c;那就是能够在无需复现玩家反馈的卡顿现象时&#xff0c;快速且准确地定位卡顿的根本原因。为了实现这一目标&#xff0c;UWA GPM 2.0推出了全新功能 - 卡顿帧堆栈&#xff0c;旨在为开发团队提供高效、精准的卡顿分析工具。在这篇…

【人工智能】蓝耘智算平台盛大发布DeepSeek满血版:开创AI推理体验新纪元

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 蓝耘智算平台 蓝耘智算平台核心技术与突破元生代推理引擎快速入门&#xff1a;三步调用大模型接口&#xff0c;OpenAI SDK无缝兼容实战用例文…

用Python+Flask打造可视化武侠人物关系图生成器:从零到一的实战全记录

用PythonFlask打造可视化武侠人物关系图生成器&#xff1a;从零到一的实战全记录 一、缘起&#xff1a;一个程序小白的奇妙探索之旅 作为一个接触Python仅13天的编程萌新&#xff0c;我曾以为开发一个完整的应用是遥不可及的事情。但在DeepSeek的帮助下&#xff0c;我竟用短短…

Mac远程桌面软件哪个好用?

远程桌面软件能帮助我们快速的远程控制另一台电脑&#xff0c;从而提供远程帮助&#xff0c;或者进行远程办公。那么&#xff0c;对macOS系统有什么好用的Mac远程桌面软件呢&#xff1f; 远程看看是一款操作简单、界面简洁的远程桌面软件&#xff0c;支持跨平台操作&#xff0…

华为云 | 快速搭建DeepSeek推理系统

DeepSeek&#xff08;深度求索&#xff09;作为一款国产AI大模型&#xff0c;凭借其高性能、低成本和多模态融合能力&#xff0c;在人工智能领域崛起&#xff0c;并在多个行业中展现出广泛的应用潜力。 如上所示&#xff0c;在华为云解决方案实践中&#xff0c;华为云提供的快速…

Unity 内置渲染管线各个Shader的用途和性能分析,以及如何修改Shader(build in shader 源码下载)

文章目录 所有Shader分析路径&#xff1a;Standard路径&#xff1a;Nature/路径&#xff1a;UI/路径&#xff1a;Particles/Particles/Standard SurfaceParticles/Standard Unlit 路径&#xff1a;Unlit/Unlit/TextureUnlit/ColorUnlit/TransparentUnlit/Transparent CutoutUnl…

概率分布与概率密度

前言 本文隶属于专栏《机器学习数学通关指南》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见《机器学习数学通关指南》 正文 &#x1f50d; 1. 概率分布基…

【C++】类与对象:深入理解默认成员函数

类与对象&#xff1a;深入理解默认成员函数 引言1、默认成员函数概述2、构造函数与析构函数2.1 默认构造函数2.2 析构函数 3、拷贝控制成员3.1 拷贝构造函数3.2 赋值运算符重载 4、移动语义&#xff08;C11&#xff09;4.1 移动构造函数4.2 移动赋值运算符 5、三五法则与最佳实…

LINUX网络基础 - 网络编程套接字,UDP与TCP

目录 前言 一. 端口号的认识 1.1 端口号的作用 二. 初识TCP协议和UDP协议 2.1 TCP协议 TCP的特点 使用场景 2.2 UDP协议 UDP的特点 使用场景 2.3 TCP与UDP的对比 2.4 思考 2.5 总结 三. 网络字节序 3.1 网络字节序的介绍 3.2 网络字节序思考 四. socket接口 …

夸父工具箱(安卓版) 手机超强工具箱

如今&#xff0c;人们的互联网活动日益频繁&#xff0c;导致手机内存即便频繁清理&#xff0c;也会莫名其妙地迅速填满&#xff0c;许多无用的垃圾信息悄然占据空间。那么&#xff0c;如何有效应对这一难题呢&#xff1f;答案就是今天新推出的这款工具软件&#xff0c;它能从根…

Apache nifi demo 实验

Apache nifi 是个数据流系统&#xff0c;可以通过配置 自定义的流程来实现数据的转换。 比如可以配置一个流程&#xff0c;读取数据库里的数据&#xff0c;再转换&#xff0c;最后保存到本地文件。 这样可以来实现一些数据转换的操作&#xff0c;而不用特地编写程序来导入导出。…

VSCode知名主题带毒 安装量900万次

目前微软已经从 Visual Studio Marketplace 中删除非常流行的主题扩展 Material Theme Free 和 Material Theme Icons&#xff0c;微软称这些主题扩展包含恶意代码。 统计显示这些扩展程序的安装总次数近 900 万次&#xff0c;在微软实施删除后现在已安装这些扩展的开发者也会…

Java自动拆箱装箱/实例化顺序/缓存使用/原理/实例

在 Java 编程体系中&#xff0c;基本数据类型与包装类紧密关联&#xff0c;它们各自有着独特的特性和应用场景。理解两者之间的关系&#xff0c;特别是涉及到拆箱与装箱、实例化顺序、区域问题、缓存问题以及效率问题。 一、为什么基本类型需要包装类 泛型与集合的需求 Java…

蓝桥杯复盘记录004(2023)

涉及知识点 1.深搜 2.单调队列滑动窗口 3.位运算 4.并查集 题目 1.lanqiao3505 思路&#xff1a; dfs(index, weight, cnt) index表示瓜的索引&#xff0c; weight等于买瓜的重量&#xff0c; cnt表示买了多少瓜。 递归终止条件&#xff1a;1.如果瓜买完了&#xff0c;归…

【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…