題目描述:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。
定義的樹:
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);
}
打印: