题目:输入两棵二叉树A和B,判断A是不是B的子结构。二叉树结点定义如下:
typedef struct BinaryTreeNode { int value; struct BinaryTreeNode *pLeft; struct BinaryTreeNode *pRight; }BT, *PBT;
像这种有关树的问题中涉及到的指针的操作是非常多的,所以分析题的时候,如果能够以画图的形式分析清楚,那么编代码的时候便不至于漏洞百出。现在来看看题目,要判断在树A中是否存在和树B一样结构的子树,我们可以把它分成两步:第一步:在树A中找到和树B根结点值一样的结点R;第二步再来判断树A中以R为根结点的子树是否包含和树B一样结构的子树。
我们画两棵树来分析一下:
我们首先是尝试着在A中查找和B的根结点相同的结点,其实就是遍历A。很幸运的,遇到的第一个结点就和B的根结点值相同。接下来,我们需要进一步刚刚找到的那个结点的下面是否依然具有与B相同的结构。显然,A中根结点的左子结点值为8,而B的左子结点值为9,所以我们排除了这个结点。
接着找下一个结点,我们找到了A的根结点的左孩子,它的值也为8;进一步的我们要判断现在这个结点的子树是否具有和B相同结构的子树。如此便要比较它的左孩子与B根结点的左孩子,发现相等,在比较它们各自的右孩子,发现相等。然后想继续比较下面,发现B再下面没有结点了,于是乎,我们确认S中包含有和B一样结构的子树。
从思路上可以很清晰的想到用递归解决这个问题是比较简单的。下面我们来实现:
int does_tree1_has_tree2(PBT pa, PBT pb) { if (NULL == pb) return 1; if (NULL == pa) return 0; if (pa->value != pb->value) return 0; return does_tree1_has_tree2(pa->pLeft, pb->pLeft) && does_tree1_has_tree2(pa->pRight, pb->pRight); } int sub_tree(PBT pa, PBT pb) { int ret = 0; //不存在 if (NULL != pa && NULL != pb) { if (pa->value == pb->value) { ret = does_tree1_has_tree2(pa, pb); } if (!ret) { ret = sub_tree(pa->pLeft, pb); } if (!ret) { ret = sub_tree(pa->pRight, pb); } } return ret; }
在这个程序中 一定要考虑到边界条件的检查。如传入的指针为空的情况该怎么处理。最后为了确保代码的正确性,写完之后一定要进行测试(最好写程序之前就想好测试用例,如此一来,写程序的时候也就1清楚会出现哪些情况)。测试用例也要尽可能包含各种不同情况,每种情况找一个代表来测试。如输入的树A和树B中头结点为空指针的情况,结点只有左孩子而没有又孩子(或相反)的情况,只有根结点的情况。这里就不在贴上测试代码了。
查找子树
最新推荐文章于 2021-06-13 13:10:42 发布