題目:輸入一個整數和一棵二元樹。從樹的根結點開始往下訪問一直到葉結點所經過的所有結點形成一條路徑。
打印出和與輸入整數相等的所有路徑。
例如輸入整數22和如下二元樹
10
/ \
5 12
/ \
4 7
則打印出兩條路徑:10, 12和10, 5, 7。
分析:考查對樹這種基本數據結構以及遞歸函數的理解。
當訪問到某一結點時,把該結點添加到路徑上,並累加當前結點的值。如果當前結點爲葉結點並且當前路徑的和剛好等於輸入的整數,
則當前的路徑符合要求,我們把它打印出來。如果當前結點不是葉結點,則繼續訪問它的子結點。當前結點訪問結束後,遞歸函數將自動回到父結點。
因此我們在函數退出之前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父結點時路徑剛好是根結點到父結點的路徑。
我們不難看出保存路徑的數據結構實際上是一個棧結構,因爲路徑要與遞歸調用狀態一致,而遞歸調用本質就是一個壓棧和出棧的過程。
#include<iostream>
#include<vector>
using namespace std;
struct BinaryTreeNode
{
int m_value;
BinaryTreeNode *m_pleft;
BinaryTreeNode *m_pright;
};
void creatBinaryTree(BinaryTreeNode * &r,int m)
{
if(r==NULL)
{
BinaryTreeNode *t=new BinaryTreeNode();
t->m_pleft=NULL;
t->m_pright=NULL;
t->m_value=m;
r=t;
}
if(m < r->m_value)
creatBinaryTree(r->m_pleft,m);
if(m > r->m_value)
creatBinaryTree(r->m_pright,m);
//if(m == r->m_value)
// cout<<"加入重複結點!"<<endl;
}
void FindPath(BinaryTreeNode *cur,int expectedvalue,int curvalue,vector<int> &path)
{
if(cur==NULL)
return;
if(cur->m_value>expectedvalue)
return;
curvalue+=cur->m_value;
path.push_back(cur->m_value);
bool isleaf=(!cur->m_pleft&&!cur->m_pright);
if(curvalue==expectedvalue&&isleaf)
{
vector<int>::iterator iter=path.begin();
for(;iter!=path.end();iter++)
cout<<*iter<<" ";
cout<<endl;
}
if(cur->m_pleft)
FindPath(cur->m_pleft,expectedvalue,curvalue,path);
if(cur->m_pright)
FindPath(cur->m_pright,expectedvalue,curvalue,path);
curvalue-=cur->m_value;
path.pop_back();
}
int main()
{
BinaryTreeNode *r=NULL;
int value=22;
vector<int> vec;
creatBinaryTree(r,10);
creatBinaryTree(r,5);
creatBinaryTree(r,12);
creatBinaryTree(r,4);
creatBinaryTree(r,3);
creatBinaryTree(r,7);
FindPath(r,22,0,vec);
return 0;
}