面試中關於二叉樹的常見習題(持續更新)

這兩天看了幾篇關於面試中關於二叉樹的常見問題,感到思路得到了很大的拓展,對遞歸的理解也更加深入,下面將問題及代碼總結如下:

Q1:求二叉樹第k層的結點個數
A:遞歸思路:空樹返回0;只有根節點返回1;其餘情況對左右子樹進行遞歸,返回左右子樹(k-1)層結點數之和

/*求二叉樹第k層的結點個數*/
/*空樹返回0,只有根節點返回1,其餘情況對左右子樹進行遞歸,返回左右子樹(k-10層)結點數之和*/
Status GetKthLevelNum(BiTree T,int k){
    int numL,numR;/*聲明兩個變量,分別代表左右子樹結點個數*/
    if(!T)
       return 0;
    if(k==1)
       return 1;
    else{
        numL=GetKthLevelNum(T->Lchild,k-1);
        numR=GetKthLevelNum(T->Rchild,k-1);
        return (numL+numR);
    }
}

Q2:比較兩棵二叉樹是否同構
A:遞歸思路:兩棵樹均爲空,返回true;有一棵爲空一棵不爲空,返回false;其餘情況遞歸判斷兩棵樹的左子樹和右子樹,最後返回兩個布爾值經過”與”之後的值

/*比較兩棵二叉樹是否同構*/
/*兩棵樹均爲空,返回true;有一棵爲空一棵不爲空,返回false;其餘情況遞歸判斷兩棵樹的左子樹和右子樹,最後返回兩個布爾值經過"與"之後的值*/
bool BiTreeCmp(BiTree T1,BiTree T2){
    bool result1,result2;/*兩個布爾值用來標記兩棵樹的子樹是否同構*/
    if(!T1&&!T2)
       return true;
    if((!T1&&T2)||(T1&&!T2)) 
       return false;
    else{
        result1=BiTreeCmp(T1->Lchild,T2->Lchild);
        result2=BiTreeCmp(T1->Rchild,T2->Rchild);
        return (result1&&result2);
    }
}

Q3:求二叉樹鏡像
A:遞歸思路:樹返回ERROR;非空則遞歸處理左右子樹,最後把處理後的pRight賦值給左子樹,pLeft賦值給右子樹即可

/*求二叉樹鏡像*/
/*空樹返回ERROR;非空則遞歸處理左右子樹,最後把處理後的pRight賦值給左子樹,pLeft賦值給右子樹即可*/
BiTree Mirror(BiTree T){
    BiTree pLeft,pRight;
    if(!T)
       return ERROR;
    else{
        pLeft=Mirror(T->Lchild);
        pRight=Mirror(T->Rchild);
        T->Lchild=pRight;
        T->Rchild=pLeft;
    }
}

Q4:尋找最低公共祖先

/*查找節點,供FindCommonParent()進行調用*/
/*若爲空樹或節點爲空,返回ERROR;節點爲根節點時直接返回TRUE;其餘情況分別在左右子樹中遞歸查找即可*/
bool FindNode(BiTree T,BiTree pNode){
    if(!pNode||!T)
        return false;
    if(pNode==T)
        return true;
    else{
        /*在左子樹中找到*/
        if(FindNode(T->Lchild,pNode))
           return true;
        /*左子樹中未找到,在右子樹中遞歸查找*/
        else
           FindNode(T->Rchild,pNode);
    }
}

/*尋找最低公共祖先*/
BiTree FindCommonParent(BiTree T,BiTree pNode1,BiTree pNode2){
    if(!T||!pNode1||!pNode2)
       return NULL;
    /*若兩節點一左一右,則最低公共祖先爲根節點*/ 
    if(FindNode(T->Lchild,pNode1)){
        if(FindNode(T->Rchild,pNode2))
           return T;
        /*若節點2在左子樹,則在左子樹上遞歸尋找最低公共祖先*/
        else
           FindCommonParent(T->Lchild,pNode1,pNode2);
    }
    /*若節點1在右子樹*/
    else{
        /*節點2在左子樹,返回根節點*/
        if(FindNode(T->Lchild,pNode2))
           return T;
        /*節點2在右子樹,則在右子樹上遞歸查找*/
        else
            FindCommonParent(T->Rchild,pNode1,pNode2);
    }
}

Q5:求二叉樹兩節點間最大距離
A:

int Max(int num1,int num2){
    return num1>num2? num1:num2;
}

/*求二叉樹兩節點間最大距離*/
/*二叉樹兩節點最大距離可能有三種:
0.左子樹上的最大距離 1.右子樹上最大距離 2.左右子樹中的節點到根節點最大距離之和*/
int GetMaxDistance(BiTree T,int &MaxLeft,int &MaxRight){
    if(!T)
       return ERROR;
    int maxLL,maxLR,maxRL,maxRR;/*maxLL爲根節點左子樹的左子樹部分,其他以此類推*/ 
    int MaxDistLeft,MaxDistRight;/*這兩個變量指左右子樹上的節點到根節點的最大距離*/
    /*如果有左子樹*/
    if(T->Lchild){
        /*遞歸求解左子樹中的節點到根節點最大距離*/ 
        MaxDistLeft=GetMaxDistance(T->Lchild,maxLL,maxLR);
        /*求解左子樹內部的最大距離*/
        MaxLeft=Max(maxLL,maxLR)+1;
    } 
    else{
        MaxLeft=0;
        MaxDistLeft=0;
    }
    if(T->Rchild){
        MaxDistRight=GetMaxDistance(T->Rchild,maxRL,maxRR);
        MaxRight=Max(maxRL,maxRR)+1;
    }
    else{
        MaxRight=0;
        MaxDistRight=0;
    }
    /*返回 左右子樹最大距離 和 左右子樹中的節點到根節點的距離之和 中的較大值*/
    return Max(Max(MaxDistLeft,MaxDistRight),MaxLeft+MaxRight);
} 

2016-05-22日更新
Q5:根據先序遍歷和中序遍歷重建二叉樹
A:思路見代碼註釋

/*根據前中序遍歷序列重建二叉樹*/
/*基本思路:在先序遍歷中找到首元素,其爲樹根節點;再找出中序遍歷時根節點的位置,左邊爲左子樹,右邊爲右子樹。之後遞歸恢復其左右子樹*/
/*接收三個參數,在此給出解釋:pPreorder爲先序遍歷得到的字符串,pInorder同理,Nodenum爲節點數*/
BiTree ReBuildTree(TElemType * pPreorder,TElemType * pInorder,int Nodenum) {
    if(!pPreorder||!pInorder||Nodenum<=0)
        return ERROR;
    BiTree p=(BiTree)malloc(sizeof(BiTreeNode));
    if(!p)
        return ERROR;
    /*將先序遍歷的第一個賦值給p的數據域*/
    p->data=pPreorder[0];
    p->Lchild=NULL;
    p->Rchild=NULL;
    /*rootposition記錄了根節點在中序遍歷的位置*/
    int rootposition=-1;
    for(int i=0; i<Nodenum; i++) {
        if(pInorder[i]==p->data) {
            rootposition=i;
            break;
        }
    }
    int NodenumLeft=rootposition;
    TElemType * pPreorderLeft=pPreorder+1;
    TElemType * pInorderLeft=pInorder;
    /*遞歸恢復左子樹*/
    p->Lchild=ReBuildTree(pPreorderLeft,pInorderLeft,NodenumLeft);

    int NodenumRight=Nodenum-rootposition-1;
    TElemType * pPreorderRight=pPreorder+NodenumLeft+1;
    TElemType * pInorderRight=pInorder+NodenumLeft+1;
    /*遞歸恢復右子樹*/
    p->Rchild=ReBuildTree(pPreorderRight,pInorderRight,NodenumRight);
    return p;
}

持續更新中,敬請關注

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