题目:输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
例如输入整数22和如下二元树
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。
二元树结点的数据结构定义为:
struct BinaryTreeNode // a node in the binary tree
{
int m_nValue; // value of node
BinaryTreeNode *m_pLeft; // left child of node
BinaryTreeNode *m_pRight; // right child of node
};
这里其实用到了树的深度搜索,在深度搜索的过程中将遍历到的每一个节点的值相加,当扫描到叶节点的时候, 判断和是否为期待和,如果是,则打印出路径,否则,不打印,然后将该节点从栈中删除,便返回到父节点的其他节点,继续操作。
void FindPath
(
BinaryTreeNode* pTreeNode, // a node of binary tree
int expectedSum, // the expected sum
std::vector<int>& path, // a path from root to current node
int currentSum // the sum of path
)
{ // 如果当前节点为空,则返回
if(!pTreeNode)
return;
// 当前和的值为当前节点的值加上当前和的值,并且将其压入栈中
currentSum += pTreeNode->m_nValue;
path.push_back(pTreeNode->m_nValue);
//判断该节点是否在叶节点,如果是叶节点,打并且路径上节点的和值等于期待的和,那么打印此这条路径
bool isLeaf = (!pTreeNode->m_pLeft && !pTreeNode->m_pRight);
if(currentSum == expectedSum && isLeaf)
{
std::vector<int>::iterator iter = path.begin();
for(; iter != path.end(); ++ iter)
std::cout << *iter << '\t';
std::cout << std::endl;
}
//如果当前节点不是叶节点,那么可以遍历它的左右子树,这里就用到了递归的思想
if(pTreeNode->m_pLeft)
FindPath(pTreeNode->m_pLeft, expectedSum, path, currentSum);
if(pTreeNode->m_pRight)
FindPath(pTreeNode->m_pRight, expectedSum, path, currentSum);
// 最后,必须把当前节点弹出栈,回朔到父节点
path.pop_back();
}
由此看来,本道题目其实就是考察树的深度搜索和栈的先进先出这条性质,当某一条路径打印完毕之后,函数的最后一条语句就是起这样一条作用,将以当前节点为根的路径删除,有的读者可能会有疑问,为什么将当前节点弹出就等于删除了以当前节点为根的路径了,因为这里用到了递归,将当前节点弹出之前,其实它的子树的所有节点都已经进行过path.pop_back();操作了,最后该路径只剩下当前节点了。。。
本篇文章对应何海涛博客http://zhedahht.blog.163.com/blog/static/254111742007228357325/
略有改动