要求:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的
节点形成一条路径。二叉树的节点定义如下:
struct BTNode { int data; BTNode *leftChild; BTNode *rightChild; };
思路:因为求路径是从根节点到叶子结点,所以我们可以考虑二叉树的先序遍历框架,如下所示:
void preOrder(BTNode *root) { if(root!=NULL) { cout<<root->data; preOrder(root->leftChild); preOrder(root->rightChild); } }但是在二叉树的递归框架中,回溯到父节点时我们是不能获取到前面递归经过的路径上的节点的值的,因为这些操作是系统自动用递归工作栈来完成的,所以我们得自己定义一个数组把经过的路径上的节点保存下来,每访问到一个节点就把该结点添加到路径数组中,当到达叶子节点时,我们看路径数组中的值的和是否满足,满足则打印输出数组中的节点路径,每当从子节点回到父节点的时候,要将路径数组中的值去除。即递归入栈的时候要添加节点的值,递归出栈的时候要去除节点的值。
基于上述思路代码如下:
void initFindPath(BTNode *root,int sum) { if(root==NULL) return ; std::vector<int> path; int currentSum=0; findPath(root,sum,path,currentSum); } //该函数充分利用了二叉树前序遍历的递归算法框架,在原算法的基础上添加了一个保存路径的数组,递归入栈,就将 //当前结点的值加入数组,递归出栈就去除当前结点在路径数组中的值,本质上是一个回溯算法。 void findPath(BTNode *root,int sum,std::vector<int> &path,int currentSum) { currentSum+=root->data;//将二叉树前序遍历中的输出根节点操作替换为求和及入栈操作。 path.push_back(root->data); bool isLeaf=(root->leftChild==NULL)&&( root->rightChild==NULL); if(currentSum==sum&&isLeaf) { cout<<"找到一条路径如下:"<<endl; vector<int>::iterator iter=path.begin(); for(;iter!=path.end();iter++) { cout<<*iter<<' '; } cout<<endl; } if(root->leftChild) findPath(root->leftChild,sum,path,currentSum); if(root->rightChild) findPath(root->rightChild,sum,path,currentSum); path.pop_back();//在返回到父节点之前,删除路径中当前结点的值,本质上是回溯 }