一、同构的概念:

给定两棵二叉树 T1 和 T2,如果T2可以通过若干次左右孩子互换就变成T1,那么我们称这两棵树是同构的

例1:下图两棵树同构,因为对T2,交换A左右孩子;交换B左右孩子,交换G左右孩子,经过3次交换后,T2=T1,即两棵树全等,所以说这两棵树是同构的。

例2:下面两棵树异构,因为对T2-B的左右孩子不等于T1-B,所以异构。

二、二叉树的表示:

数组表示法:一棵结点数为5的二叉树可以表示为下图

缺点:浪费空间,5个结点就需要13个空间来保存,增删改不方便。

优点:空间地址连续,能够快速查找

链表表示法:一棵结点数为5的二叉树可以表示为下图

优点:增删改方便。

缺点:查找速度慢,空间地址不连续。

静态链表表示法:静态链表是物理结构是数组,但是使用了链表的思想的一种抽象数据结构。很好的融合了两者的优点,空间地址连续,查找起来快,且不浪费空间。

三、递归法,判断二叉树是否同构

分析:两棵二叉树同构的情况有下列几种:

① 均为空

② 全等

③ 交换左右子树后全等

据此,可以用代码实现:

def isomorphic(R1, R2, T1, T2):"""R1: T1 的根节点R2:T2 的根节点T1:T1树T2:T2数判断两棵树是否同构同构的情况:① 两棵树都为空 (全等)② 两棵树全等③ 左/右结点交换后全等"""# 两棵树都为空if R1==NULL and R2==NULL:return Trueif R1.element == R2.element:if R1.left==NULL and R2.left==NULL:  # 左子树为空,右子树同构return isomorphic(R1=T1.get(R1.right), R2=T2.get(R2.right), T1=T1, T2=T2)if (R1.left!=NULL and R2.left!=NULL) and \(T1.get(R1.left).element == T2.get(R2.left).element):  # 两棵树全等return (isomorphic(R1=T1.get(R1.left), R2=T2.get(R2.left), T1=T1, T2=T2) andisomorphic(R1=T1.get(R1.right), R2=T2.get(R2.right), T1=T1, T2=T2))else:  # 交换后全等return (isomorphic(R1=T1.get(R1.left), R2=T2.get(R2.right), T1=T1, T2=T2) andisomorphic(R1=T1.get(R1.right), R2=T2.get(R2.left), T1=T1, T2=T2))return False

四、队列法

分析:我们可以参考层序遍历来做,每个结点都当作一棵树,只要所有结点同构,那么这两棵树就同构。

def isomorphic2(R1, R2, T1, T2):"""R1: T1 的根节点R2:T2 的根节点T1:T1树判断是否同构"""s = QueueArr()s.addQ((R1, R2))flag = Truewhile (not (s.isEmpty())):r1, r2 = s.deleteQ()if r1==NULL and r2==NULL:continue # 空树全等if (r1!=NULL and r2!=NULL) and (r1.element == r2.element):if r1.left==NULL and r2.left==NULL:  # 左子树为空,右子树同构s.addQ((T1.get(r1.right), T2.get(r2.right)))continueif (r1.left!=NULL and r2.left!=NULL) \and (T1.get(r1.left).element == T2.get(r2.left).element):s.addQ((T1.get(r1.left), T2.get(r2.left)))s.addQ((T1.get(r1.right), T2.get(r2.right)))continueelse:s.addQ((T1.get(r1.left), T2.get(r2.right)))s.addQ((T1.get(r1.right), T2.get(r2.left)))continuereturn Falsereturn flag

五、堆栈法

分析:

① 堆栈法和先序遍历算法差不多,遇到一个结点,先判断当前元素是否相等;

② 若不相等,直接抛出异构;若相等,继续判断T1,T2左子树,当T2左子树不等于T1左子树时,交换T2左右子树,并且把此时两个结点压入栈,因为左子树判断完需要回头判断右子树。

③ 当遍历完左子树,跳到兄弟右子树,回到步骤1;

如此循环,直到整棵树遍历完,如果都没有抛出异构,那么这两棵树同构。

def isomorphic3(R1, R2, T1, T2):"""判断是否同构"""s = ArrStack()p1 = R1p2 = R2while ((p1!=NULL and p2!=NULL) or (not (s.isEmpty()))):while(p1!=NULL and p2!=NULL):  # 遍历左子树if p1.element!= p2.element:  # 判断当前指针所指的元素是否相等return Falses.push((p1, p2))if (p1.left==NULL and p2.left==NULL):...elif not ((p1.left!=NULL and p2.left!=NULL) and (T1.get(p1.left).element == T2.get(p2.left).element)):t = p2.leftp2.left = p2.rightp2.right = tp1 = T1.get(p1.left)p2 = T2.get(p2.left)if p1==NULL and p2==NULL:  # 跳到右子树p1, p2 = s.pop()p1 = T1.get(p1.right)p2 = T2.get(p2.right)else:return Falsereturn True

六、效率对比

现有T1,T2

分别调用3种算法

效率对比如下

可以看到堆栈实现速度最快,比递归快7-8倍。

判断两棵二叉树是否同构,三种实现方式(递归、队列、堆栈)相关推荐

  1. python代码判断两棵二叉树是否相同

    python代码判断两棵二叉树是否相同 给定两个二叉树,编写一个函数来校验它们是否相同.如果两个树在结构上相同,并且结点具有相同的值,则认为它们是相同的. 判断两个二叉树是否是相同的,相同的依据是 二 ...

  2. Python算法——判断两棵二叉树是否相等

    要求: 如何判断两颗树是否相等?(两棵树相等是指这两课树有着相同的结构,并且在相同位置上的结点有相同的值) 分析: 如果两颗二叉树root1, root2相等, 那么root1和root2结点的值相同 ...

  3. 判断两棵二叉树是否相等(Java实现)

    判断树是否相等,就是判断树中的每一个节点是否相等,根节点和根节点做比较,根节点的左子节点和左子节点作比较,右子节点和右子节点作比较,直到没有节点比较为止,中间只要一个节点不相等,就返回false,只有 ...

  4. 二叉树常见算法题(单值二叉树、二叉树的最大深度、反转二叉树、判断两颗二叉树是否相同、对称二叉树、一颗二叉树是否是另一颗二叉树的子树)

    这里的代码都是递归实现的,再强调下二叉树的概念,二叉树的构成有两种情况: 1.空树 2.根节点 + 左子树 + 右子树(这里的左子树和右子树又是一颗二叉树) 可以看出二叉树就是递归定义的,下面的算法题 ...

  5. 6.36③ 若已知两棵二叉树B1和B2皆为空,或者皆 不空且B1的左、右子树和B2的左、右子树分别相似, 则称二叉树B1和B2相似。试编写算法,判别给定两 棵二叉树是否相似。

    6.36③  若已知两棵二叉树B1和B2皆为空,或者皆 不空且B1的左.右子树和B2的左.右子树分别相似, 则称二叉树B1和B2相似.试编写算法,判别给定两 棵二叉树是否相似. 要求实现下列函数: S ...

  6. 【数据结构】判断两棵树是否相等的算法

    下面用先根遍历的思路描述算法的步骤: 若两棵二叉树都为空,则两棵二叉树相等,返回true; 若两棵二叉树都非空,则 若根结点的值相等,则继续判断它们的左子树是否相等: 若左子树相等,则再继续判断它们的 ...

  7. 详解二叉树的三种遍历方式(递归、迭代、Morris算法)

    详解二叉树的三种遍历方式(递归.迭代.Morris算法) 最重要的事情写在前面:遍历顺序不一定就是操作顺序!!! 递归解法 首先,一颗二叉树它的递归序列是一定的,导致其前中后序不同的原因只不过是访问节 ...

  8. 剑指offer——复习1:二叉树三种遍历方式的迭代与递归实现

    剑指offer--复习1:二叉树三种遍历方式的迭代与递归实现 20180905更新:这个博客中的解法不是很好,看相应的LeetCode题目笔记~~~ 我感觉此博客中的说法更容易让人理解:https:/ ...

  9. 二叉树的三种遍历方式(递归、非递归和Morris遍历)

    二叉树的三种遍历方式(递归.非递归和Morris遍历) 原文:http://www.linuxidc.com/Linux/2015-08/122480.htm 二叉树遍历是二叉树的最基本的操作,其实现 ...

最新文章

  1. C++多线程:package_task异步调用任何目标执行操作
  2. 深度学习之单目深度估计:无监督学习篇
  3. linux下mq的mc.sh在哪?,RocketMQ的安装与使用
  4. idea创建maven web项目需要注意的一些细节
  5. Rabbit的工作(2)
  6. 1583. 统计不开心的朋友
  7. springaop----springaop的使用(一)
  8. ACM国际编程大赛夺冠,李现和他的队员们一定把这8本书翻烂了
  9. 不要解决:如何将JavaScript集合与目标相匹配
  10. 使用weblogic部署应用
  11. SpringCloud——pom文件初始配置
  12. 使用adb命令解锁Android手机
  13. 超分辨率中PSNR的计算与bicubic插值
  14. Python 打怪兽游戏
  15. Geoserver入门操作系列之二:创建图层样式
  16. excel 置信区间 计算_用Excel求置信区间.ppt
  17. C# PDF的创建,替换文本,插入图片
  18. 在vue中使用高德地图获取坐标与地址信息(包含点击+搜索)
  19. CAD数据不通过ArcGIS导出为MDB
  20. 游戏设计文档的功能及类型

热门文章

  1. golang 本地缓存
  2. 修改windows下用户名
  3. Android Sdk和安卓各个版本的匹配
  4. java notify 唤醒_java notify()的唤醒
  5. 用Java写一个信息管理系统与学习心得
  6. USB2.0如何区分low speed、full speed 和high speed
  7. Java语言进阶:网络编程入门
  8. DSPE-PEG-Streptavidin;Streptavidin-PEG-DSPE;磷脂聚乙二醇链霉亲和素,科研用试剂
  9. vue引入阿里巴巴iconfont图标(简单易懂)
  10. 无人驾驶领域货车已进入商用,货车司机失业潮即将来临?