二叉樹(4)

摺紙問題
把一段紙條豎着放在桌子上,然後從紙條下方向上方對摺1次,壓出摺痕後展開,此時摺痕是凹下去的。若從紙條下方向上方對摺2次,壓出摺痕後展開,此時有三條摺痕,從上到下依次是下摺痕、下摺痕和上摺痕。給定一個輸入參數N,代表紙條都從下邊向上方連續對摺N次,請從上到下打印所有摺痕的方向。
這裏寫圖片描述
是一顆滿二叉樹結構,
實現先左再中,最後右的中序遍歷,就是所有摺痕的打印順序(從下到上)。用遞歸實現。

案例
一顆二叉樹原本是搜索二叉樹,但其中有兩個節點調換了位置,使得這棵二叉樹不再是搜索二叉樹,請找到這兩個錯誤節點。
答:
1.對二叉樹中序遍歷,依此出現的節點值會一直升序,如果兩個節點值錯了,會出現降序。
2.若中序遍歷時節點值出現了兩次降序,第一個錯誤的節點爲第一次降序時較大的節點,第二個錯誤的節點爲第二次降序時較小的節點。
這裏寫圖片描述
3.若中序遍歷時節點值出現了一次降序,第一個錯誤的節點爲這次降序時較大的節點,第二個錯誤的節點爲這次降序時較小的節點。
這裏寫圖片描述

案例
從二叉樹的節點A出發,可以向上或向下走,但沿途的節點只能經過一次,當到達節點B時,路徑上的節點數叫作A到B的距離。比如大家看到的圖中,節點4和節點2的距離爲2,節點5和節點6的距離爲5。給定一顆二叉樹的頭節點head,求整顆樹上節點間的最大距離。
這裏寫圖片描述
分析:
一個以h爲頭的樹上,最大距離只可能來自以下三種情況:
情況一:h的左子樹上的最大距離。
情況二:h的右子樹上的最大距離。
情況三:h左子樹上離h左孩子最遠的距離,加上h自身這個節點,再加上h右子樹上離h右孩子的最遠距離,也就是兩個節點分別來自h兩側子樹的情況。
三個值中最大的那個就是以h爲頭的整顆樹上最遠的距離。
步驟:
1、整個過程爲後序遍歷,在二叉樹的每顆子樹上執行步驟2.
2、假設子樹頭爲h,處理h左子樹,得到兩個信息,左子樹上的最大距離記爲LMax1,左子樹上距離h左孩子的最遠距離記爲LMax2。處理h右子樹得到右子樹上的最大距離記爲RMax1,距離h右孩子的最遠距離爲RMax2。那麼跨h節點情況下的最大距離爲LMax2+1+RMax2,這個值與LMax1和RMax1比較,最大值爲 以h爲頭的整棵樹上的最大距離。
3、LMax2+1就是h左子樹上離h最遠的點到h的距離,RMax2+1就是h右子樹上離h最遠的點到h的距離,選兩者中最大的一個作爲h樹上距離h最遠的距離返回。
4、用返回長度爲2的數組的方式,返回兩個值
PS:理解是遞歸思想,但覺得不太對。這個不太懂,還需要細看。

解:
這題寫了很久,但仔細想想,感覺沒那麼難,就是求子樹深度的問題

#include<iostream>
#include<string>
#include<stack>
#include<queue>
using namespace std;

class BinaryTreeNode  
{
public:
    char data;  
    BinaryTreeNode *Left;  
    BinaryTreeNode *Right;  
}; 

//創建二叉樹,順序依次爲中間節點->左子樹->右子樹
void createBiTree(BinaryTreeNode* &T)   //這裏加上&意思是傳遞的參數爲指針的引用,括號裏面等價於 BiTreeNode* &T
 {                                 //這樣的意義在於在函數執行過後,傳遞進來的指針會發生改變(引用的作用),不可以去掉&
     char c;
     cin >> c;
     if('#' == c)               //當遇到#時,令樹的根節點爲NULL,從而結束該分支的遞歸
         T = NULL;
     else
     {
         T = new BinaryTreeNode;
         T->data=c;
         createBiTree(T->Left);
         createBiTree(T->Right);
     }
 }

int treeDepth(BinaryTreeNode* root){
    if(root==NULL){
        return 0;
    }
    if(root->Left==NULL){
        return treeDepth(root->Right)+1;
    }
    if(root->Right==NULL){
        return treeDepth(root->Left)+1;
    }
    return treeDepth(root->Right)>treeDepth(root->Left)?treeDepth(root->Right)+1:treeDepth(root->Left)+1;
}

int max1(int a,int b,int c){
    if(a>=b){
        if(a>=c){
            return a;
        }
        return c;
    }
    else if(b>=c)
        return b;
    else return c;
}


int maxjuli(BinaryTreeNode* root){
    if(root==NULL)
        return 0;
    int Lmax1=maxjuli(root->Left);    
    int Lmax2=treeDepth(root->Left);        
    int Rmax1=maxjuli(root->Right);
    int Rmax2=treeDepth(root->Right);   
    return max1(Lmax1,Rmax1,Lmax2+Rmax2);
}

int main(){
    BinaryTreeNode* T;               //聲明一個指向二叉樹根節點的指針               
    createBiTree(T);               //abcd##e#f#g#h###i##
    cout<<"二叉樹創建完成!"<<endl; 
    cout<<"二叉樹最長距離:"<<endl;
    int a=maxjuli(T);
    cout<<a<<endl;

    return 0;
}

案例
給定一顆二叉樹的頭節點head,已知其中所有節點的值都不一樣,找到含有節點最多的搜索二叉子樹,並返回這顆子樹的頭節點。例如,大家現在看到的圖1這顆樹,最大的搜索子樹就是圖2這棵樹。
這裏寫圖片描述
以節點node爲頭的樹中,最大的搜索二叉子樹只可能來自以下兩種情況:
1、來自node左子樹上的最大搜索二叉子樹是以node左孩子爲頭的,並且來自node右子樹上的最大搜索二叉樹是以node右孩子爲頭的,node左子樹上的最大搜索二叉子樹的最大值小於node的節點值,node右子樹上的最大搜索二叉子樹的最小值大於node的節點值,那麼以節點node爲頭的整顆樹都是搜索二叉樹。
2、若不滿足第一種情況,說明以node爲頭的樹整體不能連成搜索二叉樹。這種情況下,以node爲頭的樹上的最大搜索二叉子樹是來自node左子樹上的最大搜索二叉子樹和來自node右子樹上的最大搜索二叉子樹之間,節點數較多的那個。
求解具體過程爲:
1.整體過程是二叉樹的後序遍歷。
2.遍歷到當前節點記爲cur,先遍歷cur的左子樹並收集4個信息,分別是左子樹上最大搜索二叉樹的頭節點,節點數,最小值和最大值。再遍歷cur的右子樹並收集4個信息,分別是右子樹上最大搜索二叉樹的頭節點,節點數,最小值和最大值
3.根據步驟2所收集的信息,判斷是否滿足第一種情況,也就是是否以cur爲頭的子樹,整體都是搜索二叉樹。如果滿足第一種情況,就返回cur節點,如果滿足第二種情況,就返回左子樹和右子樹各自的最大搜索二叉樹中,節點數較多的那個樹的頭節點。
4.對於如何返回4個信息,可使用全局變量更新的方式實現,或返回長度爲4的數組。
難點:遞歸過程、收集信息並返回上層。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章