這兩天看了幾篇關於面試中關於二叉樹的常見問題,感到思路得到了很大的拓展,對遞歸的理解也更加深入,下面將問題及代碼總結如下:
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;
}
持續更新中,敬請關注