确定一个二叉树是另一个二叉树的子树
2015-03-12 21:56
393 查看
问题: 给定两个binary trees, check 第一个二叉树是否为第二个二叉树的子树。
例如, 如下:
则 S是T的子树。
解决办法:
(simple solution)对T进行preorder的traversal, 对于每一个visited node, 我们检查以这个节点为node的根的subtree 是否和S 是identical的。 程序如下:
Time complexity: worst case: O(mn), 其中m, n分别是给定的两棵树的节点数。
注意, 上面的算法的复杂度太高了。 我们下面采用一个更加高效的办法。
这个简单的方法的时间复杂度为O(n)。
思路是基于这样的一个事实。
中序遍历(in order traversal) + 前序遍历/后序遍历 能够唯一的identify一个二叉树。 也就是说, 当对S进行中序遍历和前序遍历(或者换成后续遍历)得到两个字符串, 分别是对T进行对应遍历得到的两个字符串的子字符串的时候, 那么S是T的子树。 具体实现步骤如下:
(1)对T进行前序和中序遍历, 将遍历的结果分别存放在两个辅助数组 inT[] 和 preT[]。
(2)对待检测的子树S进行前序和中序遍历, 将遍历的结果分别存放在 inS[] 和 perS[]。
(4) 如果 inS 是 inT[] 的子数组, 并且 preS[] 是 preT[] 的子数组, 那么我们就说S是T的子树。
EDIT
程序代码如下:
运行结果如下:
例如, 如下:
Tree S 10 / \ 4 6 \ 30
Tree T 26 / \ 10 3 / \ \ 4 6 3 \ 30
则 S是T的子树。
解决办法:
(simple solution)对T进行preorder的traversal, 对于每一个visited node, 我们检查以这个节点为node的根的subtree 是否和S 是identical的。 程序如下:
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; // a binary tree node has data, left child, // and right child struct node { int data; node* left; node* right; }; // a utility function to check whether trees with // roots as root1 and root2 are identical bool areIdentical(node* root1, node* root2) { // base case if(root1 == NULL && root2 == NULL) return true; if(root1 == NULL || root2 == NULL) return false; // check if the data of both roots is the same and // data on left and right subtrees are identical or not return (root1 -> data == root2 -> data && areIdentical(root1 -> left, root2 -> left) && areIdentical(root1 -> right, root2 -> right)); } // this function returns if S is subtree of T, // otherwise, false bool isSubtree(node* T, node* S) { // base case if(S == NULL) return false; if(T == NULL) return false; // check the tree with root as the current node if(areIdentical(T, S)) return true; // if the tree with root as current node doesnot // match them, try left ans right subtree one by one return isSubtree(T -> left, S) || isSubtree(T -> right, S); } // helper function that allocates a new node with // with given data node* newNode(int data) { node* Node = new node; Node -> data = data; Node -> left = NULL; Node -> right = NULL; return Node; } /* Driver program to test above function */ int main() { /* Construct the following tree 26 / \ 10 3 / \ \ 4 6 3 \ 30 */ struct node *T = newNode(26); T->right = newNode(3); T->right->right = newNode(3); T->left = newNode(10); T->left->left = newNode(4); T->left->left->right = newNode(30); T->left->right = newNode(6); /* Construct the following tree 10 / \ 4 6 \ 30 */ struct node *S = newNode(10); S->right = newNode(6); S->left = newNode(4); S->left->right = newNode(30); if (isSubtree(T, S)) printf("Tree S is subtree of tree T"); else printf("Tree S is not a subtree of tree T"); return 0; }运行结果:
Time complexity: worst case: O(mn), 其中m, n分别是给定的两棵树的节点数。
注意, 上面的算法的复杂度太高了。 我们下面采用一个更加高效的办法。
这个简单的方法的时间复杂度为O(n)。
思路是基于这样的一个事实。
中序遍历(in order traversal) + 前序遍历/后序遍历 能够唯一的identify一个二叉树。 也就是说, 当对S进行中序遍历和前序遍历(或者换成后续遍历)得到两个字符串, 分别是对T进行对应遍历得到的两个字符串的子字符串的时候, 那么S是T的子树。 具体实现步骤如下:
(1)对T进行前序和中序遍历, 将遍历的结果分别存放在两个辅助数组 inT[] 和 preT[]。
(2)对待检测的子树S进行前序和中序遍历, 将遍历的结果分别存放在 inS[] 和 perS[]。
(4) 如果 inS 是 inT[] 的子数组, 并且 preS[] 是 preT[] 的子数组, 那么我们就说S是T的子树。
Inorder and Preorder traversals of the big tree are. inT[] = {a, c, x, b, z, e, k} preT[] = {z, x, a, c, b, e, k} Inorder and Preorder traversals of small tree are inS[] = {a, c, x, b} preS[] = {x, a, c, b} We can easily figure out that inS[] is a subarray of inT[] and preS[] is a subarray of preT[].
EDIT
The above algorithm doesn't work for cases where a tree is present in another tree, but not as a subtree. Consider the following example. Tree1 x / \ a b / c Tree2 x / \ a b / \ c d Inorder and Preorder traversals of the big tree or Tree2 are. Inorder and Preorder traversals of small tree or Tree1 are The Tree2 is not a subtree of Tree1, but inS[] and preS[] are subarrays of inT[] and preT[] respectively.
程序代码如下:
#include <iostream> #include <cstring> using namespace std; const int MAX = 100; // structure of a tree node struct Node { char key; Node* left; Node* right; }; // a utility function to create a new // binary tree node Node* newNode(char data) { Node* temp = new Node; temp -> key = data; temp -> left = NULL; temp -> right = NULL; return temp; } // a utility function to store inorder traversal // of tree rooted with root in an array arr[]. // note that i is pass by reference void storeInorder(Node* root, char arr[], int&i) { if(root == NULL) { arr[i++] = '$'; return; } storeInorder(root -> left, arr, i); arr[i++] = root -> key; storeInorder(root -> right, arr, i); } // a utility function to store preorder traversal // of tree rooted with root in an arr[]. Note that // i is passed by reference void storePreoder(Node* root, char arr[], int &i) { if(root == NULL) { arr[i++] = '$'; return; } arr[i++] = root -> key; storePreoder(root -> left, arr, i); storePreoder(root -> right, arr, i); } // this function returns true if S is a subtree of T, // otherwise, false bool isSubtree(Node* T, Node*S) { // base case if(S == NULL) return true; if(T == NULL) return false; // store Inoder traversals of T and S in // inT[0..m] and inS[0..n] int m = 0; int n = 0; char inT[MAX], inS[MAX]; storeInorder(T, inT, m); storeInorder(S, inS, n); inT[m] = '\0'; inS = '\0'; // if inS[] is not a substring of inT[], return false if(strstr(inT, inS) == NULL) return false; // store preoder traversal of T and S in preT[0..m-1] // preS[0.. n-1] m = 0, n = 0; char preT[MAX], preS[MAX]; storePreoder(T,preT, m); storePreoder(S, preS, n); preT[m] = '\0'; preS = '\0'; if(strstr(preT, preS) == NULL) return false; return true; } // Driver program to test above function int main() { Node *T = newNode('a'); T->left = newNode('b'); T->right = newNode('d'); T->left->left = newNode('c'); T->right->right = newNode('e'); Node *S = newNode('a'); S->left = newNode('b'); S->left->left = newNode('c'); S->right = newNode('d'); if (isSubtree(T, S)) cout << "Yes: S is a subtree of T"; else cout << "No: S is NOT a subtree of T"; return 0; }
运行结果如下:
相关文章推荐
- 数据结构——确定一个二叉树是不是另一个二叉树的子树(2)
- 数据结构——确定一个二叉树是不是另一个二叉树的子树
- 剑指offer15--判断一个二叉树是不是另一个的子树
- 2个二叉树A、B,树的每个节点上都有一个整数值。如何判断A与B是否其中一个是另一个的子树?
- 判断一个二叉树是否是另一个二叉树的子树
- 如何判断一个二叉树是否为另一个二叉树的子树
- 求一个二叉树是否为另一个二叉树的子树
- 两棵树都是空树,或者非空且具有相似的左子树和右子树,则这两棵树是相似的。编写一个函数以确定是否两棵二叉树是相似的
- 检测一个二叉树是否是另一个二叉树的子树
- 判断一个二叉树是否是另一个二叉树的子树
- 判断一个二叉树是否是另一个的子树
- 描述一个运行时间为Θ(nlgn)的算法,给定n个整数的集合S和另一个整数x,该算法能确定S中是否存在两个其和刚好为x的元素
- 有一个二叉树, 节点全部为整数,如何找到一个子树,它所有节点的和最大?要求编程序实现。
- 给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。这里规定大小写为不同字符,且考虑字符串重点空格。 给定一个string stringA和一个string stri
- 树的计数问题和通过一个中序遍历序列和一个先序遍历序列来确定一棵二叉树
- 树的计数问题和通过一个中序遍历序列和一个先序遍历序列来确定一棵二叉树
- CCI 1.3 确定一个字符串重排列后,是否变成另一个字符串
- 递归算法练习与整理(一):判断一个二叉树是不是另一个二叉树的的子结构
- 百度笔试题:判断一个二叉树是否是另一颗二叉树的子树
- 判断一个树是否为另一个树的子树