题目:输入两个二叉树A和B,判断B是不是A的子结构。

思路:遍历A树找到B树的根节点,然后再判断左右子树是否相同。不相同再往下找。重复改过程。

子结构的描述如下图所示:

C++代码:

#include<iostream>
using namespace std;
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
BinaryTreeNode* ConstructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder)
{
int rootValue=startPreorder[];
BinaryTreeNode* root=new BinaryTreeNode();
root->m_nValue=rootValue;
root->m_pLeft=root->m_pRight=NULL;
if(startPreorder==endPreorder)
{
if(startInorder==endInorder&&*startPreorder==*startInorder)
{
return root;
}
else
throw std::exception("Invalid put!");
}
//通过中序遍历序列找到根节点
int* rootInorder=startInorder;
while(rootInorder<=endInorder&&*rootInorder!=rootValue)
{
++rootInorder;
}
if(rootInorder==endInorder&&*rootInorder!=rootValue)
{
throw std::exception("Invalid put");
}
int leftLength=rootInorder-startInorder;
int rightLength=endInorder-rootInorder;
int* leftPreorderEnd=startPreorder+leftLength;
if(leftLength>)
{
//递归构建左子树
root->m_pLeft=ConstructCore(startPreorder+,leftPreorderEnd,startInorder,rootInorder-);
}
if(rightLength>)
{
//递归构建右子树
root->m_pRight=ConstructCore(leftPreorderEnd+,endPreorder,rootInorder+,endInorder);
}
return root;
} BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
if(preorder==NULL||inorder==NULL||length<=)
{
throw std::exception("Invalid put!");
}
return ConstructCore(preorder,preorder+length-,inorder,inorder+length-);
}
bool DoesTree1HasTree2(BinaryTreeNode* pRoot1,BinaryTreeNode* pRoot2)
{
if(pRoot2==NULL)
return true;
if(pRoot1==NULL)
return false;
if(pRoot1->m_nValue !=pRoot2->m_nValue)
return false;
return DoesTree1HasTree2(pRoot1->m_pLeft,pRoot2->m_pLeft)&&DoesTree1HasTree2(pRoot1->m_pRight,pRoot2->m_pRight);
}
bool hasSubTree(BinaryTreeNode* pRoot1,BinaryTreeNode* pRoot2)
{
bool result=false;
if(pRoot1!=NULL&&pRoot2!=NULL)
{
if(pRoot1->m_nValue==pRoot2->m_nValue)
result=DoesTree1HasTree2(pRoot1,pRoot2);
if(!result)
result=hasSubTree(pRoot1->m_pLeft,pRoot2);
if(!result)
result=hasSubTree(pRoot1->m_pRight,pRoot2);
}
return result;
}
void PrintTreeNode(BinaryTreeNode* pNode) {
if(pNode != NULL)
{
printf("value of this node is: %d\n", pNode->m_nValue);
if(pNode->m_pLeft != NULL)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is null.\n");
if(pNode->m_pRight != NULL)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is null.\n");
}
else
{
printf("this node is null.\n");
}
printf("\n");
} //递归打印左右子树
void PrintTree(BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot);
if(pRoot != NULL)
{
if(pRoot->m_pLeft != NULL)
PrintTree(pRoot->m_pLeft);
if(pRoot->m_pRight != NULL)
PrintTree(pRoot->m_pRight);
}
}
//递归删除左右子树 void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != NULL)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight;
delete pRoot;
pRoot = NULL;
DestroyTree(pLeft);
DestroyTree(pRight);
}
} void main()
{
const int length1 = ;
const int length2 = ;
int preorder1[length1] = {, , , , , , , };
int inorder1[length1] = {, , , , , , , };
int preorder2[length2]={,,};
int inorder2[length2]={,,};
BinaryTreeNode *root1 = Construct(preorder1, inorder1, length1);
BinaryTreeNode *root2 =Construct(preorder2, inorder2, length2);
PrintTree(root1);
PrintTree(root2);
if(hasSubTree(root1,root2))
cout<<"hello!"<<endl;
else
cout<<"world!"<<endl;
}

Java代码:

public class IsSubTree {
public static class BinaryTreeNode
{
int m_nValue;
BinaryTreeNode m_pLeft;
BinaryTreeNode m_pRight;
};
public static BinaryTreeNode ConstructBiTree(int[] preOrder,int start,int[] inOrder,int end,int length)
{
//参数验证 ,两个数组都不能为空,并且都有数据,而且数据的数目相同
if (preOrder == null || inOrder == null
|| inOrder.length != preOrder.length || length <= 0) {
return null;
}
int value=preOrder[start];
BinaryTreeNode root=new BinaryTreeNode();
root.m_nValue=value;
root.m_pLeft=root.m_pRight=null;
//递归终止条件:子树只有一个节点
if (length == 1){
if(inOrder[end]==value)
return root;
else
throw new RuntimeException("Invalid input");
}
//分拆子树的左子树和右子树
int i = 0;
while (i < length) {
if (value == inOrder[end - i]) {
break;
}
i++;
}
if(i==length)
throw new RuntimeException("Invalid input");
//建立子树的左子树
root.m_pLeft = ConstructBiTree(preOrder, start + 1, inOrder, end - i - 1, length - 1 - i);
//建立子树的右子树
root.m_pRight = ConstructBiTree(preOrder, start + length - i, inOrder, end, i );
return root;
}
public static boolean DoesTree1HasTree2(BinaryTreeNode pRoot1,BinaryTreeNode pRoot2)
{ //树A存在树B的根节点时,判断B的左右子树是否也存在A树中。
if(pRoot2==null)
return true;
if(pRoot1==null)
return false;
if(pRoot1.m_nValue !=pRoot2.m_nValue)
return false;
return DoesTree1HasTree2(pRoot1.m_pLeft,pRoot2.m_pLeft)&&DoesTree1HasTree2(pRoot1.m_pRight,pRoot2.m_pRight);
}
public static boolean hasSubTree(BinaryTreeNode pRoot1,BinaryTreeNode pRoot2)
{ //判断是否是子树
boolean result=false;
if(pRoot1!=null&&pRoot2!=null)
{
if(pRoot1.m_nValue==pRoot2.m_nValue)
result=DoesTree1HasTree2(pRoot1,pRoot2);//树A存在树B的根节点时,判断B的左右子树是否也存在A树中。
if(!result)
result=hasSubTree(pRoot1.m_pLeft,pRoot2);//在左子树中找B的根节点。
if(!result)
result=hasSubTree(pRoot1.m_pRight,pRoot2);//在右子树中找B的根节点。
}
return result;
}
public static void PrintTreeNode(BinaryTreeNode pNode)
{
if(pNode !=null)
{
System.out.println("the Node is:"+pNode.m_nValue);
if(pNode.m_pLeft != null)
System.out.println( "left child is:"+pNode.m_pLeft.m_nValue);
else
System.out.println("left child is null.\n");
if(pNode.m_pRight != null)
System.out.println("right child is:"+pNode.m_pRight.m_nValue);
else
System.out.println("right child is null.\n");
}
else
{
System.out.println("this node is null.\n");
}
System.out.println();
} //递归打印左右子树
public static void PrintTree(BinaryTreeNode pRoot)
{
PrintTreeNode(pRoot);
if(pRoot !=null)
{
if(pRoot.m_pLeft != null)
PrintTree(pRoot.m_pLeft);
if(pRoot.m_pRight != null)
PrintTree(pRoot.m_pRight);
}
} public static void main(String[] args)
{
int preorder1[] = {1, 2, 4, 7, 3, 5, 6, 8};
int inorder1[] = {4, 7, 2, 1, 5, 3, 8, 6};
int preorder2[]={3,5,6};
int inorder2[]={5,3,6};
BinaryTreeNode root1 = ConstructBiTree(preorder1,0, inorder1,7, preorder1.length);
BinaryTreeNode root2 = ConstructBiTree(preorder2,0, inorder2,2, preorder2.length);
PrintTree(root1);
PrintTree(root2);
if(hasSubTree(root1,root2)
System.out.println("存在子树关系!");
else
System.out.println("不存在子树关系!");
}
}

剑指offer-第三章高质量代码(树的子结构)的更多相关文章

  1. 剑指offer—第三章高质量代码(数值的整数次方)

    高质量的代码:容错处理能力,规范性,完整性.尽量展示代码的可扩展型和可维护性. 容错处理能力:特别的输入和处理,异常,资源回收. 规范性:清晰的书写,清晰的布局,合理的命名. 完整性:功能测试,边界测 ...

  2. 剑指offer—第三章高质量代码(o(1)时间删除链表节点)

    题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点,链表节点与函数的定义如下:struct ListNode{int m_nValue;ListNode* m_pValue ...

  3. 剑指offer—第三章高质量代码(合并两个排序链表)

    题目:输入员两个递增排序的链表,合并这两个链表并使新的链表中的结点仍然是按照递增排序的. 思路:首先,定义两个头节点分别为Head1和Head2的链表,然后比较第一个节点的值,如果是Head1-> ...

  4. 剑指offer—第三章高质量的代码(按顺序打印从1到n位十进制数)

    题目:输入一个数字n,按照顺序打印出1到最大n位十进制数,比如输入3,则打印出1,2,3直到最大的3位数999为止. 本题陷阱:没有考虑到大数的问题. 本题解题思路:将要打印的数字,看成字符串,不足位 ...

  5. 剑指offer第三章

    剑指offer第三章 1.数值的整数次方 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. class Solution { public ...

  6. 剑指offer-第三章高质量代码(反转链表)

    题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转链表的头节点. 思路:对一个链表反转需要三个指针操作来保证链表在反转的过程中保证不断链,给链表一个行动指针pNode,对pNode指向的节 ...

  7. 《剑指offer》第二十六题(树的子结构)

    // 面试题26:树的子结构 // 题目:输入两棵二叉树A和B,判断B是不是A的子结构. #include <iostream> struct BinaryTreeNode { doubl ...

  8. 剑指offer第五章

    剑指offer第五章 1.数组中出现次数超过一半的数 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组 ...

  9. 剑指offer第七章&第八章

    剑指offer第七章&第八章 1.把字符串转换成整数 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 输入描述: 输入一个字符串 ...

随机推荐

  1. Linux系统下使用pwgen生成密码的使用教程

    pwgen生成的密码易于记忆且相当安全.从技术上来说,容易记忆的密码不会比随机生成的密码更加安全.但是,在大多数情况下,pwgen生成的密码已经足够安全,除了网银密码等需要高安全等级的情况外.使用易于 ...

  2. UNIDAC的安装

    UNIDAC的安装1.在source目录中找到对应Delphi版本目录的make.bat文件,修改其中的 set IdeDir="D:\Application\DelphiXE2指到你的de ...

  3. 【北京集训D2T3】tvt

    [北京集训D2T3]tvt \(n,q \le 1e9\) 题目分析: 首先需要对两条路径求交,对给出的四个点的6个lca进行分类讨论.易于发现路径的交就是这六个lca里面最深的两个所形成的链. 然后 ...

  4. SDWebImage支持URL不变时更新图片内容

    SDWebImage在iOS项目中是一个很常用的开源库,而且众所周知的是,它是基于URL作为Key来实现图片缓存机制的.在90%左右的情况下, 图片与URL是一一对应的,即使服务器修改了图片也会相应的 ...

  5. JavaScript 打印控件

    JavaScript 打印控件 github地址 https://github.com/DoersGuild/jQuery.print 使用前需要引入jQuery $("#mapDiv&qu ...

  6. centOS7.4 thinkPHP nginx 支持pathinfo和rewrite

    server { listen 80; server_name www.demo.com mayifanx.com; root /data/www/demo; index index.php inde ...

  7. 智课雅思词汇---二十四、名词性后缀ary(也是形容词后缀)

    智课雅思词汇---二十四.名词性后缀ary(也是形容词后缀) 一.总结 一句话总结:很多词缀即是名词词缀也是形容词词缀,很多词即是名词也是形容词 1.名词性后缀-tude? 词根词缀:-tude [来 ...

  8. python学习笔记(xlwt/xlrd下载安装)

    python支持处理Excel 可以使用xlwt xlrd 模块 分别在https://pypi.python.org/pypi/xlwt  和 https://pypi.python.org/pyp ...

  9. Win10/Server2016镜像集成离线补丁

    Win10镜像集成离线补丁 因为正常安装系统后再打补丁比较漫长,可以事先做好打过补丁的iso,备将来使用. 以管理员身份运行cmd,然后通过dism提取.挂载.集成补丁.保存install.wim镜像 ...

  10. DGA GAN——GAN在安全中的应用

    DGA的模型:https://github.com/Yuren-Zhong/DeepDGA CNN.LSTM.双向LSTM 论文可以看https://openreview.net/pdf?id=BJL ...