题目:
输入一个整数和一棵二元树。从根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
分析:
当访问到某一结点时,把该结点添加到路径上,并累加当前结点的值。如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。如果当前结点不是叶结点,则继续访问它的子结点。当前结点访问结束后,递归函数将自动回到父结点。因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是根结点到父结点的路径。我们不难看出保存路径的数据结构实际上是一个栈结构,因为路径要与递归调用状态一致,而递归调用本质就是一个压栈和出栈的过程。
参考代码:
方法一:(递归)
void FindPath(TreeNode* const pRoot, int exceptSum,int curSum, std::vectorpath) { TreeNode* p =pRoot; if(p==NULL) return ; curSum +=p->data; path.push_back(p); if((curSum==exceptSum) && (p->leftChild==NULL && p->rightChild==NULL)) { std::vector ::iterator iter=path.begin(); for( ; iter!=path.end(); iter++) { cout << (*iter)->data << "\t"; } cout <<std::endl; } if(p->leftChild) FindPath(p->leftChild,exceptSum,curSum,path); if(p->rightChild) FindPath(p->rightChild,exceptSum,curSum,path); curSum -=p->data; path.pop_back(); }
方法二:(迭代)
请考虑
方法三:(递归得到所有路径,分别求出每条路径的和值)
递归打印二叉树所有路径:
void FindAllPath(TreeNode* const pRoot, std::vectorpath)//递归打印所有路径 { TreeNode* p =pRoot; if(p==NULL) return ; path.push_back(p); if( p->leftChild==NULL && p->rightChild==NULL)//isLeaf then print path { std::vector ::iterator iter=path.begin(); for( ; iter!=path.end(); iter++) { cout << (*iter)->data << "\t"; } } if(p->leftChild) FindAllPath(p->leftChild,path); if(p->rightChild) FindAllPath(p->rightChild,path); }
那么通过对所有路径中的每一条和值得到:
void FindPath(TreeNode* const pRoot, std::vectorpath,int ExceptSum) { TreeNode* p =pRoot; int sum=0; if(p==NULL) return ; path.push_back(p); if( p->leftChild==NULL && p->rightChild==NULL) { std::vector ::iterator iter=path.begin(); for( ; iter!=path.end(); iter++) { sum += (*iter)->data; } if(sum==ExceptSum) { iter=path.begin(); for( ; iter!=path.end(); iter++) { cout << (*iter)->data << "\t"; } cout <<std::endl; }else{ sum=0; } } if(p->leftChild) FindPath(p->leftChild,path,ExceptSum); if(p->rightChild) FindPath(p->rightChild,path,ExceptSum); }
方法四:(非递归得到所有路径,分别求出每条路径的和值)
非递归打印所有路径:转自:非递归打印二叉树的所有路径
void FindAllPath2(TreeNode* const pRoot,std::vectorpath) { if(pRoot==NULL) return ; enum Tag{goLeft, goRight, goBack }; vector vec_flag; TreeNode* p=pRoot; path.push_back(p); vec_flag.push_back(goLeft); while( !path.empty()) { TreeNode *curTreeNode = path.back(); Tag curFlag = vec_flag.back(); switch(curFlag) { case goLeft: vec_flag.pop_back(); vec_flag.push_back(goRight); if(curTreeNode->leftChild != NULL) { path.push_back(curTreeNode->leftChild); vec_flag.push_back(goLeft); } break; case goRight: vec_flag.pop_back(); vec_flag.push_back(goBack); if(curTreeNode->rightChild != NULL) { path.push_back(curTreeNode->rightChild); vec_flag.push_back(goLeft); } break; case goBack: if(NULL == curTreeNode->leftChild && NULL == curTreeNode->rightChild) { std::vector ::iterator iter=path.begin(); for( ; iter!=path.end(); iter++) { cout << (*iter)->data << "\t"; } cout << endl; } vec_flag.pop_back(); path.pop_back(); break; default: break; }//switch-end }//while-end }
那么通过对所有路径中的每一条和值得到:
代码略;