您的位置:首页 > 其它

二叉树中和为某一值的路径

2016-08-08 22:57 260 查看
例子:

                 10

         5               12

   4         7

由于路径是从根节点出发到叶结点,也就是说路径总是以根节点。在树的前序、中序、后序三种遍历方式中,只有前序遍历是首先访问根节点的。

按照前序遍历的顺序遍历上图,在访问结点10之后,就会访问结点5。从二叉树结点的定义可以看出,在本体的二叉树结点中没有指向父节点的指针,访问到结点5的时候,我们是不知道前面经过了哪些结点的,除非我们把经过的路径结点保存下来。每访问到一个结点的时候,我们都把当前的结点添加到路径中去。到达结点5时,路径中包含两个结点,它们的值分别是10和5、接下来遍历到结点4,我们把这个结点也添加到路径中。这个时候已经到达了叶节点,但路径上三个结点的值之和是19.这个和不等于22,因此不是符合要求的路径。

我们接着要遍历其他结点。在遍历下一个结点之前,先要从结点4回到结点5,再去遍历结点5的右子节点7.值得注意的是,回到结点5的时候,由于结点4已经不在前往结点7的路径上了,我们需要把结点4从路径中删除。接下来访问到结点7的时候,再把该节点添加到路径中,此时路径中三个结点10、5/7之和刚好是22,是一条符合要求的路径。

我们最后要遍历的结点是12,。在遍历这个结点之前,需要先经过结点5回到10。同样,每一次当从子节点回到父节点的时候,我们都需要在路径上删除子节点。最后从结点10到达结点12的时候,路径上的两个结点的值之和也是22,因此这也是一条符合条件的路径。

分析完之后,总结规律如下:

当用前序遍历的方式访问到某一结点时,我们把该结点添加到路径上,并累加该结点的值。如果该结点为叶结点并且路径中结点值的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。如果当前结点不是叶结点,则继续访问它的子节点。当前结点访问结束后,递归函数将自动回到它的父节点的值,因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值。

typedef struct BinaryTreeNode{
int val;
BinaryTreeNode* left;
BinaryTreeNode* right;
}BinaryTreeNode;
void FindPath(BinaryTreeNode* pRoot, int expectedSum)
{
if (pRoot == NULL) return;
vector<int> path;
int currentSum = 0;
FindPath(pRoot, expectedSum, path, currentSum);
}
void FindPath(BinaryTreeNode* pRoot,int expectedSum,vector<int>& path,int currentSum){
currentSum += pRoot->val;
path.push_back(pRoot->val);
//如果是叶子结点,并且路径上结点的和等于输入的值
bool isLeaf = (pRoot->left == NULL) && (pRoot->right == NULL);
if (currentSum == expectedSum&&isLeaf){
cout << "A path is found:";
vector<int>::iterator iter = path.begin();
for (; iter != path.end(); ++iter)
cout << *iter << " ";
cout << endl;
}
//如果不是叶子结点,则遍历它的子节点
if (pRoot->left != NULL)
FindPath(pRoot->left,expectedSum,path,currentSum);
if (pRoot->right != NULL)
FindPath(pRoot->right,expectedSum,path,currentSum);
//在返回到父节点之前,在路径上删除当前结点
path.pop_back();
currentSum -= pRoot->val;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: