// 面试题26:树的子结构
// 题目:输入两棵二叉树A和B,判断B是不是A的子结构。 #include <iostream> struct BinaryTreeNode
{
double m_dbValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
}; bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);
bool Equal(double num1, double num2); bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)//遍历树1,看看有没有树2的头结点
{
bool result = false; if (pRoot1 != nullptr && pRoot2 != nullptr)//对于树结构,时刻判断节点为空的情况
{
if (Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))//注意该题树结构中值的类型是double,不能用==
result = DoesTree1HaveTree2(pRoot1, pRoot2);//如果头结点一样,就看看是否真的包含
if (!result)
result = HasSubtree(pRoot1->m_pLeft, pRoot2);//如果头结点不一样,就开始遍历全树
if (!result)
result = HasSubtree(pRoot1->m_pRight, pRoot2);
} return result;
} bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
if (pRoot2 == nullptr)//如果这个节点为空代表什么,把树2熬到头就赢了
return true; if (pRoot1 == nullptr)//如果这个节点为空代表什么,完了,树1先熬到头了
return false; if (!Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))//都在啊,那等不等啊
return false; return DoesTree1HaveTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) &&
DoesTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);//相等,那就递归的检测
} bool Equal(double num1, double num2)
{
if ((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))
return true;
else
return false;
} // ====================辅助测试代码====================
BinaryTreeNode* CreateBinaryTreeNode(double dbValue)
{
BinaryTreeNode* pNode = new BinaryTreeNode();
pNode->m_dbValue = dbValue;
pNode->m_pLeft = nullptr;
pNode->m_pRight = nullptr; return pNode;
} void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
if (pParent != nullptr)
{
pParent->m_pLeft = pLeft;//这个时候不用说pLeft为不为空了,为空又怎样
pParent->m_pRight = pRight;
}
} void DestroyTree(BinaryTreeNode* pRoot)
{
if (pRoot != nullptr)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight; delete pRoot;
pRoot = nullptr; DestroyTree(pLeft);
DestroyTree(pRight);
}
} // ====================测试代码====================
void Test(const char* testName, BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2, bool expected)
{
if (HasSubtree(pRoot1, pRoot2) == expected)
printf("%s passed.\n", testName);
else
printf("%s failed.\n", testName);
} //去吧,把能想到全想到 // 树中结点含有分叉,树B是树A的子结构
// 8 8
// / \ / \
// 8 7 9 2
// / \
// 9 2
// / \
// 4 7
void Test1()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3);
ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5);
ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, pNodeB2, pNodeB3); Test("Test1", pNodeA1, pNodeB1, true); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树中结点含有分叉,树B不是树A的子结构
// 8 8
// / \ / \
// 8 7 9 2
// / \
// 9 3
// / \
// 4 7
void Test2()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA6 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA7 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, pNodeA2, pNodeA3);
ConnectTreeNodes(pNodeA2, pNodeA4, pNodeA5);
ConnectTreeNodes(pNodeA5, pNodeA6, pNodeA7); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, pNodeB2, pNodeB3); Test("Test2", pNodeA1, pNodeB1, false); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树中结点只有左子结点,树B是树A的子结构
// 8 8
// / /
// 8 9
// / /
// 9 2
// /
// 2
// /
//
void Test3()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, pNodeA2, nullptr);
ConnectTreeNodes(pNodeA2, pNodeA3, nullptr);
ConnectTreeNodes(pNodeA3, pNodeA4, nullptr);
ConnectTreeNodes(pNodeA4, pNodeA5, nullptr); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, pNodeB2, nullptr);
ConnectTreeNodes(pNodeB2, pNodeB3, nullptr); Test("Test3", pNodeA1, pNodeB1, true); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树中结点只有左子结点,树B不是树A的子结构
// 8 8
// / /
// 8 9
// / /
// 9 3
// /
// 2
// /
//
void Test4()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, pNodeA2, nullptr);
ConnectTreeNodes(pNodeA2, pNodeA3, nullptr);
ConnectTreeNodes(pNodeA3, pNodeA4, nullptr);
ConnectTreeNodes(pNodeA4, pNodeA5, nullptr); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, pNodeB2, nullptr);
ConnectTreeNodes(pNodeB2, pNodeB3, nullptr); Test("Test4", pNodeA1, pNodeB1, false); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树中结点只有右子结点,树B是树A的子结构
// 8 8
// \ \
// 8 9
// \ \
// 9 2
// \
// 2
// \
// 5
void Test5()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, nullptr, pNodeA2);
ConnectTreeNodes(pNodeA2, nullptr, pNodeA3);
ConnectTreeNodes(pNodeA3, nullptr, pNodeA4);
ConnectTreeNodes(pNodeA4, nullptr, pNodeA5); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, nullptr, pNodeB2);
ConnectTreeNodes(pNodeB2, nullptr, pNodeB3); Test("Test5", pNodeA1, pNodeB1, true); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树A中结点只有右子结点,树B不是树A的子结构
// 8 8
// \ \
// 8 9
// \ / \
// 9 3 2
// \
// 2
// \
// 5
void Test6()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA5 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, nullptr, pNodeA2);
ConnectTreeNodes(pNodeA2, nullptr, pNodeA3);
ConnectTreeNodes(pNodeA3, nullptr, pNodeA4);
ConnectTreeNodes(pNodeA4, nullptr, pNodeA5); BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB4 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, nullptr, pNodeB2);
ConnectTreeNodes(pNodeB2, pNodeB3, pNodeB4); Test("Test6", pNodeA1, pNodeB1, false); DestroyTree(pNodeA1);
DestroyTree(pNodeB1);
} // 树A为空树
void Test7()
{
BinaryTreeNode* pNodeB1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeB4 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeB1, nullptr, pNodeB2);
ConnectTreeNodes(pNodeB2, pNodeB3, pNodeB4); Test("Test7", nullptr, pNodeB1, false); DestroyTree(pNodeB1);
} // 树B为空树
void Test8()
{
BinaryTreeNode* pNodeA1 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA2 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA3 = CreateBinaryTreeNode();
BinaryTreeNode* pNodeA4 = CreateBinaryTreeNode(); ConnectTreeNodes(pNodeA1, nullptr, pNodeA2);
ConnectTreeNodes(pNodeA2, pNodeA3, pNodeA4); Test("Test8", pNodeA1, nullptr, false); DestroyTree(pNodeA1);
} // 树A和树B都为空
void Test9()
{
Test("Test9", nullptr, nullptr, false);
} int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
system("pause");
return ;
}

《剑指offer》第二十六题(树的子结构)的更多相关文章

  1. 剑指Offer(十七):树的子结构

    剑指Offer(十七):树的子结构 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/baidu_ ...

  2. 剑指Offer面试题:17.树的子结构

    一.题目:树的子结构 题目:输入两棵二叉树A和B,判断B是不是A的子结构.例如下图中的两棵二叉树,由于A中有一部分子树的结构和B是一样的,因此B是A的子结构. 该二叉树的节点定义如下,这里使用C#语言 ...

  3. 剑指Offer(书):树的子结构

    题目:输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 分析:关于二叉树大部分适应于递归结构. public boolean HasSubtree(TreeN ...

  4. 【剑指Offer】面试题26. 树的子结构

    题目 输入两棵二叉树A和B,判断B是不是A的子结构.(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值. 例如: 给定的树 A:      3     / \ ...

  5. 《剑指offer》面试题26. 树的子结构

    问题描述 输入两棵二叉树A和B,判断B是不是A的子结构.(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值. 例如: 给定的树 A:      3     / ...

  6. 《剑指offer》第六题(重要!从尾到头打印链表)

    文件main.cpp // 从尾到头打印链表 // 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值. #include <iostream> #include <sta ...

  7. 剑指offer五十六之删除链表中重复的结点

    一.题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  8. 剑指offer四十六之孩子们的游戏(圆圈中最后剩下的数,约瑟夫环问题)

    一.题目 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机指 ...

  9. 剑指offer二十六之二叉搜索树与双向链表

    一.题目 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 二.思路 对二叉搜索树中序遍历的结果即为排序的结果,在中序遍历的过程中,建 ...

  10. 剑指offer三十六之两个链表的第一个公共结点

    一.题目 输入两个链表,找出它们的第一个公共结点. 二.思路 如果存在共同节点的话,那么从该节点,两个链表之后的元素都是相同的.也就是说两个链表从尾部往前到某个点,节点都是一样的.我们可以用两个栈分别 ...

随机推荐

  1. 7.6 Models -- Finding Records

    Ember Data的store为检索一个类型的records提供一个接口. 一.Retrieving a single record(检索单记录) 1. 通过type和ID使用store.findR ...

  2. redis的5种数据结构的使用场景介绍

    一.redis 数据结构使用场景 原来看过 redisbook 这本书,对 redis 的基本功能都已经熟悉了,从上周开始看 redis 的源码.目前目标是吃透 redis 的数据结构.我们都知道,在 ...

  3. 【设置】Nginx配置文件具体配置解释

    #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 8; #全局错误日志定义类型,[ debug | ...

  4. bug管理工具为开发者工作带来哪些改变?

    BUG管理工具的主要功能是对软件开发测试过程中出现的BUG进行跟踪管理,提高开发者的工作效率与工作质量. 在实际工作中,如果没有bug管理工具的帮助,就可能会出现如下一系列的影响: 1.软件测试人员将 ...

  5. form中的fieldset标签应用

    不得不说,<fieldset>是个漂亮的家伙. 使用<fieldset>与<legend>可以设计出很好的表单. <style> fieldset:nt ...

  6. VS2010/MFC编程入门之三十一(常用控件:树形控件Tree Control 下)

    前面一节讲了树形控件Tree Control的简介.通知消息以及相关数据结构,本节继续讲下半部分,包括树形控件的创建.CTreeCtrl类的主要成员函数和应用实例. 树形控件的创建 MFC为树形控件提 ...

  7. IntelliJ IDEA 编译Java程序出现 'Error:java: 无效的源发行版: 9' 解决方法

    最新安装的IntelliJ IDEA 2018.1编译器,创建Java Project,并选择之前安装好的Eclipse配置的JDK,如图所示: 在工程中添加 Main.class, main函数中写 ...

  8. 数据仓库基础(九)Informatica小技巧(1)

    本文转载自:http://www.cnblogs.com/evencao/p/3148373.html link path:查看某个字段的来源去处,非常有参考的价值.右击你想要看的字段,选择 sele ...

  9. 2018-2019-2 20165209 《网络对抗技术》Exp5:MSF基础应用

    2018-2019-2 20165209 <网络对抗技术>Exp5:MSF基础应用 目录 一.基础问题回答和实验内容 二.攻击实例 主动攻击的实践 ms08_067 payload/gen ...

  10. C/C++之面向对象

    面向对象的三个基本特征(讲解) 面向对象的三个基本特征是:封装.继承.多态. 封装 封装最好理解了.封装是面向对象的特征之一,是对象和类概念的主要特性. 封装,也就是把客观事物封装成抽象的类,并且类可 ...