question:给定一颗二叉树,一个值。我们希望输出和为该值的所有路径。
假设树的结构如下
思路:使用一个基于先序遍历的递归过程来遍历树中每个点一次,每遍历一个点就要获得从根节点到被访问的点的累加和,并保存从根节点到当前点的路径。然后进行判断,
case1如果当前点的左右孩子都为空(叶子节点)并且累加和等于我们期望的和,那么就打印出路径;
case2如果左孩子为空,递归到最孩子;
case3如果右孩子为空,递归到右孩子;
case4如果是叶子并且当前和不等于期望和,网上回退
试下代码:
参数为值传递的代码
#include<vector>
#include<iostream>
using namespace std;
typedef struct BinaryTreeNode
{
int data;
struct BinaryTreeNode *lchild;
struct BinaryTreeNode *rchild;
}*BinTreeRoot;
void createTree1(BinaryTreeNode *&root)
{
root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
root->data = 8;
root->lchild = NULL;
root->rchild = NULL;
BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 8;
p->lchild = NULL;
p->rchild = NULL;
root->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 7;
p->lchild = NULL;
p->rchild = NULL;
root->rchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 9;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 2;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 4;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 7;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild->rchild = p;
}
void findPath(BinaryTreeNode *root, int expectedSum, int curSum, vector<int>path)
{
if (root == NULL)
return;
curSum += root->data;
path.push_back(root->data);
if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum)
{
for (auto iter = path.begin(); iter != path.end(); ++iter)
{
if (iter + 1 == path.end())
{
cout << *iter << endl;
}
else
{
cout << *iter << "->";
}
}
}
if (root->lchild != NULL)
{
findPath(root->lchild, expectedSum, curSum, path);
}
if (root->rchild != NULL)
{
findPath(root->rchild, expectedSum, curSum, path);
}
// curSum -= root->data;
// path.pop_back();
}
int main()
{
BinaryTreeNode *root = NULL;
createTree1(root);
if (root == NULL)
{
cout << "the tree is empty!" << endl;
return 0;
}
int curSum = 0;//存放从根节点到当前节点的路径和
int expectedSum;//我们期待的值
cin >> expectedSum;
vector<int>path;//存放路径
findPath(root, expectedSum, curSum, path);
return 0;
}
注意:在这个代码中存放累加和curSum、路径path的变量都是使用的值传递,而不是引用传递。因为该方法是一个递归的过程,在每一个递归栈中都有一个临时变量curSum和path。如果递归返回到上一层时,本次计算的没有影响。相反,如果使用了引用传递的,需要手动修改数据的值:
参数为引用传递的代码:
#include<vector>
#include<iostream>
using namespace std;
typedef struct BinaryTreeNode
{
int data;
struct BinaryTreeNode *lchild;
struct BinaryTreeNode *rchild;
}*BinTreeRoot;
void createTree1(BinaryTreeNode *&root)
{
root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
root->data = 8;
root->lchild = NULL;
root->rchild = NULL;
BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 8;
p->lchild = NULL;
p->rchild = NULL;
root->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 7;
p->lchild = NULL;
p->rchild = NULL;
root->rchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 9;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 2;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 4;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild->lchild = p;
p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
p->data = 7;
p->lchild = NULL;
p->rchild = NULL;
root->lchild->rchild->rchild = p;
}
void findPath(BinaryTreeNode *root, int expectedSum, int &curSum, vector<int>&path)//引用传递
{
if (root == NULL)
return;
curSum += root->data;
path.push_back(root->data);
if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum)
{
for (auto iter = path.begin(); iter != path.end(); ++iter)
{
if (iter + 1 == path.end())
{
cout << *iter << endl;
}
else
{
cout << *iter << "->";
}
}
}
if (root->lchild != NULL)
{
findPath(root->lchild, expectedSum, curSum, path);
}
if (root->rchild != NULL)
{
findPath(root->rchild, expectedSum, curSum, path);
}
curSum -= root->data;//curSum和path是引用传递,所以如果递归返回到上一层的时候,需要减去本次的累加
path.pop_back();
}
int main()
{
BinaryTreeNode *root = NULL;
createTree1(root);
if (root == NULL)
{
cout << "the tree is empty!" << endl;
return 0;
}
int curSum = 0;//存放从根节点到当前节点的路径和
int expectedSum;//我们期待的值
cin >> expectedSum;
vector<int>path;//存放路径
findPath(root, expectedSum, curSum, path);
return 0;
}
过程:假设我们希望输出和为25的所有路径;
设定以下变量:int curSum = 0;//存放当前累加和
int expectedSum = 25;//期待和
vector<int>path;//用于存放路径
BinaryTreeNode *root;//指向树中根节点的指针
(1)首先从根节点出发,curSum = 8,并且不是叶子节点,并且值不为35。
(2)由于是基于先序遍历的,接下来我们访问左孩子,累加和为8+8=16,仍然不是叶子节点。
(3)再访问8的右孩子9,累加和为25,并且是叶子节点。此时打印出路径
路径为8->8->9
(4)使用一个递归的过程,然后向上回退到节点8,并且访问8的右孩子2
(5)访问2的左孩子4,此时累加和为22.
(6)当前访问到的点4是一个叶子节点,并且累加和为22,不是我们所期待的,所以向上回退到2,并且访问2的右孩子7,此时7是叶子节点。并且和为25,所以满足要求,打印出路径
路径为:8->8->2->7