二叉樹如何實現雙親結點及求樹的高度

求二叉樹的高度,可以用遞歸的思想去求解,也可以用非遞歸的思想去求解,只不過,遞歸的代碼簡單明瞭,但是總的來說,遞歸有遞歸的好處,非遞歸當然也有非遞歸的好處。

求樹的高度的遞歸思想和遞歸建樹的思想差不多:

                                                                從最底層的子樹(結點)開始,求每顆子樹(個結點)的左子樹和右子樹的高度,返回最大的那顆子樹的高度,即每遞歸一次便加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;
}

               

發佈了37 篇原創文章 · 獲贊 11 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章