求二叉樹的高度,可以用遞歸的思想去求解,也可以用非遞歸的思想去求解,只不過,遞歸的代碼簡單明瞭,但是總的來說,遞歸有遞歸的好處,非遞歸當然也有非遞歸的好處。
求樹的高度的遞歸思想和遞歸建樹的思想差不多:
從最底層的子樹(結點)開始,求每顆子樹(個結點)的左子樹和右子樹的高度,返回最大的那顆子樹的高度,即每遞歸一次便加1
具體核心代碼如下:
int getHight(BiNode<T>*t) //遞歸尋找高度
{
int deep=0;
if(t!=NULL)
{
int lchild_hight=getHight(t->lchild); //樹的左子樹的高度
int rchild_hight=getHight(t->rchild); //樹的右子樹的高度
deep=(lchild>=rchild)?(lchild_hight+1):(rchild_hight+1); //deep取最大值
}
return deep; //返回deep
}
如果遞歸思想不太明白的,建議去看看盜夢空間喲!
關於非遞歸的思想,通過遍歷整棵二叉樹,找出葉子結點,然後在從葉子結點回溯到樹的根結點,通過結算結點個數,加1便是樹高了
具體代碼如下:
void TreeHight(BiNode<T>* &t) //中序遍歷改造爲尋找樹高
{
using std::stack;
t->father=NULL;
stack<BiNode<T>*>leafstack;//存儲葉子結點的棧
stack<BiNode<T>*>nodeStack;//存儲待訪問的結點
BiNode<T>*pointer=t;
while(!nodeStack.empty()||pointer) //棧爲空時結束遍歷
{
if(pointer){
nodeStack.push(pointer); //當前結點入棧
pointer=pointer->lchild; //轉向訪問左子樹
}
else{
pointer=nodeStack.top(); //讀取棧頂元素
if(pointer->lchild==NULL&&pointer->rchild==NULL) //判斷是否爲葉子結點
leafstack.push(pointer); //若爲葉子結點,存儲到相應的棧中
pointer=pointer->rchild; //轉向訪問右子樹
nodeStack.pop(); //棧頂元素退棧
}
}
//葉子結點的地址在leafstack棧中呈線性排列
int Hight=0;//第n個葉子結點的高度
int hight=0;//第n+1個葉子結點的高度
while(!leafstack.empty())
{
hight=0; //初始化爲0
pointer=leafstack.top(); //讀取棧頂的葉子結點
while(pointer->father!=NULL) //當葉子棧爲空時結束
{
hight++;
pointer=pointer->father;//回溯到其雙親結點
}
leafstack.pop(); //棧頂元素退棧
if(Hight<hight) //當前葉子結點的高度若比之前一個的葉子高度大,則賦值給前一個高度
Hight=hight;
}
cout<<"樹高爲:"<<hight+1<<endl;
}
當然,如果是用非遞歸思想,那我們在遍歷的時候就該用層次遍歷咯
不過過程中有一個father指針的標記倒是用到了遞歸的思想
完全代碼如下:
#include<string>
#include<iostream>
#include<stack>
using namespace std;
//二叉鏈表表示二叉樹
template<class T>
class BiNode
{
public:
T data;//節點數據
BiNode * lchild;//左孩子
BiNode * rchild;//右孩子
BiNode *father;//雙親
BiNode();
BiNode(T d){ data=d; } //new一個結點的時候就給其數據域賦值
~BiNode(){}
void createTree(BiNode<T>* &t, string pre,string in) //後序,中序
{
if(pre.length()==0)
{
t=NULL;
}
if(pre.length()!=0)
{
t=new BiNode<T>(pre[0]);
int index=in.find(pre[0]);
string in_left_str=in.substr(0, index);
string in_right_str=in.substr(index+1);
string pre_left_str=pre.substr(1, index);
string pre_right_str=pre.substr(index+1);
if(t!=NULL)
{
createTree(t->lchild,pre_left_str,in_left_str);
createTree(t->rchild,pre_right_str,in_right_str);
}
}
}
void preOrder(BiNode<T> *t)
{
if(t==NULL)
{
return ;
}
if(t!=NULL)
{
cout<<t->data;
preOrder(t->lchild);
preOrder(t->rchild);
}
}
void inOrder(BiNode<T> *t)
{
if(t==NULL)
{
return ;
}
if(t!=NULL)
{
inOrder(t->lchild);
cout<<t->data;
inOrder(t->rchild);
}
}
void TreeHight(BiNode<T>* &t) //中序遍歷改造爲尋找樹高
{
using std::stack;
t->father=NULL;
stack<BiNode<T>*>leafstack;//存儲葉子結點的棧
stack<BiNode<T>*>nodeStack;//存儲待訪問的結點
BiNode<T>*pointer=t;
while(!nodeStack.empty()||pointer) //棧爲空時結束遍歷
{
if(pointer){
nodeStack.push(pointer); //當前結點入棧
pointer=pointer->lchild; //轉向訪問左子樹
}
else{
pointer=nodeStack.top(); //讀取棧頂元素
if(pointer->lchild==NULL&&pointer->rchild==NULL) //判斷是否爲葉子結點
leafstack.push(pointer); //若爲葉子結點,存儲到相應的棧中
pointer=pointer->rchild; //轉向訪問右子樹
nodeStack.pop(); //棧頂元素退棧
}
}
//葉子結點的地址在leafstack棧中呈線性排列
int Hight=0;//第n個葉子結點的高度
int hight=0;//第n+1個葉子結點的高度
while(!leafstack.empty())
{
hight=0; //初始化爲0
pointer=leafstack.top(); //讀取棧頂的葉子結點
while(pointer->father!=NULL) //當葉子棧爲空時結束
{
hight++;
pointer=pointer->father;//回溯到其雙親結點
}
leafstack.pop(); //棧頂元素退棧
if(Hight<hight) //當前葉子結點的高度若比之前一個的葉子高度大,則賦值給前一個高度
Hight=hight;
}
cout<<"樹高爲:"<<hight+1<<endl;
}
int getHight(BiNode<T>*t) //遞歸尋找高度
{
int deep=0;
if(t!=NULL)
{
int lchild_hight=getHight(t->lchild); //樹的左子樹的高度
int rchild_hight=getHight(t->rchild); //樹的右子樹的高度
deep=(lchild>=rchild)?(lchild_hight+1):(rchild_hight+1); //deep取最大值
}
return deep; //返回deep
}
void DeFineFather(BiNode *t)//遞歸標記結點的雙親
{
if(t!=NULL)
{
if(t->lchild!=NULL)
t->lchild->father=t;
if(t->rchild!=NULL)
t->rchild->father=t;
DeFineFather(t->lchild);
DeFineFather(t->rchild);
}
}
};
int main()
{
BiNode<char>*t=NULL;
string pre="ABDFGCEH";
string in="BFDGACEH";
t->createTree(t,pre,in);
/*
cout<<"前序遍歷"<<endl;
t->preOrder(t);
cout<<endl;
cout<<"中序遍歷"<<endl;
t->inOrder(t);
cout<<endl;*/
t->DeFineFather(t);
t->TreeHight(t);
cout<<endl;
cout<<"遞歸尋求樹的高度:"<<t->getHight(t)<<endl;
return 0;
}