《剑指offer》-- (7)二叉树中和为某一值的路径

题目描述:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

定义的树:

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);
}

打印:

猜你喜欢

转载自blog.csdn.net/zhuoya_/article/details/80634782
今日推荐