题目:
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下,一直到叶结点所经过的结点形成一条路径。二叉树结点定义为:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
由于路径是从根结点出发到叶结点,因此路径总是以根结点为起始点,需要按照前序遍历的顺序遍历二叉树。
举个例子来说明问题,假如输入二叉树如下,输入的整数为22:
前序遍历,第一次从根结点到叶子结点:10-5-4,遍历的同时将这3个结点加入路径当中,值之和为19,因此需要遍历其他结点。在遍历下一个结点之前,先要从结点4回到结点5,再去遍历5的右子结点7。注意,回到5的时候,就应该将4移出路径,后面遍历7到时候,应该把7加入路径,此时路径为10-5-7,值之和为22,满足。最后需要遍历12,因此需要回到12的父结点10,同时删除10的左子结点5,以及5的子结点7,此时路径为10-12,值之和为22,满足。
总结来说,当用前序遍历的方式访问某一结点时,我们把该结点添加到路径上,并累加该结点的值。如果该结点为叶结点并且路径中结点值的和刚好等于输入的整数,则当前路径符合要求。如果当前结点不是叶结点,则继续访问它的子结点。当前结点访问结束后,递归函数将自动回到它的父结点。因此我们在函数退出只前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是从根结点到父结点的路径。因为路径要与递归调用状态一致,因此保存路径的数据结构实际上是一个栈。
void FindPath(BinaryTreeNode* pRoot,int expectedSum,std::vector<int>& path,int& currentSum)
{
currentSum+=pRoot->m_nValue;
path.push_back(pRoot->m_nValue);
//如果是叶结点,并且路径上结点的和等于输入的值,打印出路径
bool isLeaf=(pRoot->m_pLeft==NULL && pRoot->m_pRight==NULL);
if(currentSum==expected && isLeaf)
{
cout<<"FOUND PATH:";
std::vector<int>::iterator iter=path.begin();
for(;iter!=path.end();++iter)
cout<<iter<<" ";
cout<<endl;
}
//如果不是叶结点,则遍历它的子结点
if(pRoot->m_pLeft!=NULL)
FindPath(pRoot->m_pLeft,expectedSum,path,currentSum);
if(pRoot->m_Right!=NULL)
FindPath(pRoot->m_pRight,expectedSum,path,currentSum);
//返回父结点之前,删除当前结点,并在currentSum中减去当前结点的值
currentSum-=pRoot->m_nValue;
path.pop_back();
}
void Find(BinaryTreeNode* pRoot,int expectedSum)
{
if(pRoot==NULL)
return;
std::vector<int> path;
int currentSum=0;
FindPath(pRoot,expectedSum,path,currentSum);
}