查找子树

题目:输入两棵二叉树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中头结点为空指针的情况,结点只有左孩子而没有又孩子(或相反)的情况,只有根结点的情况。

这里就不在贴上测试代码了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fireplusplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值