题目:输入两个二叉树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[0]; 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>0) { //递归构建左子树 root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1); } if(rightLength>0) { //递归构建右子树 root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder); } return root; } BinaryTreeNode* Construct(int* preorder,int* inorder,int length) { if(preorder==NULL||inorder==NULL||length<=0) { throw std::exception("Invalid put!"); } return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1); } 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 = 8; const int length2 = 3; int preorder1[length1] = {1, 2, 4, 7, 3, 5, 6, 8}; int inorder1[length1] = {4, 7, 2, 1, 5, 3, 8, 6}; int preorder2[length2]={3,5,6}; int inorder2[length2]={5,3,6}; 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("不存在子树关系!");} }
时间: 2024-10-14 20:35:43