题目描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
定义的树:
typedef int elemtype;
#define END -1
typedef struct BtNode
{
struct BtNode* leftchild;
struct BtNode* rightchild;
elemtype data;
}BtNode,*pBtNode;
举例:
如上图中的一颗树,假如目标值为22,则结果应该输出的路径为:
path1:10 5 7
path2:10 12 0
解题思路:
1、可以利用递归遍历解决,每访问一个结点就将当前的值(cursum)进行累加,直到访问到叶子节点,如果与目标值相等则打印,不相等则剔除最后一个加入的,再进行计算。
static void Path1(BtNode* ptr,int target,int &cursum,vector<BtNode*>& vec)
{
if(ptr!=NULL)
{
cursum+=ptr->data;//累加
vec.push_back(ptr);
Path2(ptr->leftchild,target,cursum,vec);
if(cursum==target && ptr->leftchild==NULL && ptr->rightchild==NULL)
{
vector<BtNode*>::iterator it=vec.begin();
for(;it!=vec.end();++it)
{
cout<<(*it)->data<<" ";
}
cout<<endl;
//cout<<cursum<<endl;
}
Path2(ptr->rightchild,target,cursum,vec);
cursum-=ptr->data;//一定要放在该位置!保证当前结点的左右孩子都能访问到。将不满足的叶结点的值剔除。
vec.pop_back();
}
}
void FindPath1(BtNode* ptr,int target)
{
if(NULL==ptr)
return ;
int cursum=0;
vector<BtNode*> vec;//用该容器来保存路径
Path1(ptr,target,cursum,vec);
}
2、非递归:
思路一:利用中序遍历非递归进行修改-》不行
思路二:先序遍历非递归代码修改-》存储路径上的值有很好的切入点(在打印的地方),删除做不到-》抛弃之
思路三:采用层序遍历来进行修改,不需要一个队列,只需要一个vector容器即可。核心思想是利用数组的下标来对整颗树进行处理。-》妙哉,Do it!
实现过程:是一个怎样的vector(数组)呢?看下图:
代码:
typedef struct newNode
{
int parentindex;
BtNode* p;
public:
newNode(int i=-1,BtNode* q=NULL):parentindex(i),p(q){}
}newNode;
void PrintPath(vector<newNode>& vec,int i)//打印路径
{
int k=i;stack<elemtype> s;
for(;k!=-1;k=vec[k].parentindex)
{
s.push(vec[k].p->data);
}
while(!s.empty())
{
elemtype out=s.top();s.pop();
cout<<out<<" ";
}
cout<<endl;
}
void TheOkPath(vector<newNode>& vec,int target)//找到符合要求的路径
{
for(int i=0;i<vec.size();i++)//遍历整个vec容器
{
if(vec[i].p->leftchild==NULL && vec[i].p->rightchild==NULL)//从叶子结点处查找符合要求的路径
{
int j=i;//j表示当前结点的下标
int cursum=0;
for(;j!=-1;j=vec[j].parentindex)//求当前叶子结点到树根路径的元素之和
{
cursum+=vec[j].p->data;
}
//cursum+=vec[0].p->data;//此句不需要
if(cursum==target)//如果和与目标值相等,则打印该路径中的元素
{
PrintPath(vec,i);
}
}
}
}
static void Path2(BtNode* ptr,int target)//将每个结点都保存在vec中
{
vector<newNode> vec;
int pi=-1;//根结点的双亲索引
vec.push_back(newNode(pi,ptr));
int depth=Depth_Tree(ptr);
//将树中的所有元素都存储到vector容器中
while(pi<depth)
{
pi+=1;
if(vec[pi].p->leftchild)
{
vec.push_back(newNode(pi,vec[pi].p->leftchild));
}
if(vec[pi].p->rightchild)
{
vec.push_back(newNode(pi,vec[pi].p->rightchild));
}
}
TheOkPath(vec,target);
}
void FindPath2(BtNode* ptr,int target)
{
if(NULL==ptr)
return ;
Path2(ptr,target);
}
打印: