[英]What is the principle of calculating the height of binary tree by recursive method?
這是可以找到二叉樹高度的代碼。
int PostOrderGetHeight(BinTree BT) {
int HL,HR,MaxH;
if(BT){
HL = PostOrderGetHeight(BT->Left);
HR = PostOrderGetHeight(BT->Right);
MaxH = (HL>HR)?HL:HR;
return (MaxH+1);
}
else return 0;
}
我的困惑是為什么HL,HR,MaxH不需要初始化,以及此遞歸算法如何計算HL和HR。
如果BinTree BT不等於NULL
則由於這些語句, HL
和HR
獲得其值
HL = PostOrderGetHeight(BT->Left);
HR = PostOrderGetHeight(BT->Right);
否則,如果例如BT
或BT->Left
或BT->Right
等於NULL
則函數調用例如
PostOrderGetHeight(BT->Left);
返回0,因為該函數的定義類似於
int PostOrderGetHeight(BinTree BT) {
int HL,HR,MaxH;
if(BT){
//...
}
else return 0;
^^^^^^^^
}
在函數的遞歸調用的每次迭代中,選擇左子樹和右子樹之間的最大長度。
我們可以通過PostOrderGetHeight
方式為任何樹提供PostOrderGetHeight
作品:
因此,我們將證明它適用於高度為0的樹,因此適用於高度為1的樹,因此適用於高度為2和3的樹,依此類推。
為了證明第一部分,假設用高度為0的樹調用PostOrderGetHeight
。這意味着其根節點BT
為空。 在這種情況下,當調用例程時, else return 0;
語句執行,並且例程返回零,這是正確的。
為了證明第二部分,假設使用高度為h的樹(其中h > 0)調用PostOrderGetHeight
。
然后執行以下兩個語句:
HL = PostOrderGetHeight(BT->Left);
HR = PostOrderGetHeight(BT->Right);
觀察其中的每一個都使用BT
子樹調用PostOrderGetHeight
。 每個子樹BT->Left
和BT->Right
必須是高度小於h的樹。 由於我們假設PostOrderGetHeight
適用於高度為h @ -1的樹,因此它返回這些樹的正確高度。
那么MaxH = (HL>HR)?HL:HR;
將MaxH
設置為左子樹的高度或右子樹的高度中的較大者。 在這一點上,我們知道BT
高度比最大值大一,因為它包括更大的子樹和一個更多的節點(根節點BT
)。
然后該語句return (MAXH+1);
返回該高度。
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node* left;
struct node* right;
};
int maxDepth(struct node* node)
{
if (node==NULL)
return 0;
else
{
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
if (lDepth > rDepth)
return(lDepth+1);
else return(rDepth+1);
}
}
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Height of tree is %d", maxDepth(root));
getchar();
}
希望這可以幫助!
一步聲明和初始化變量可能更清楚。 有關更多信息,請參見此處 。
int PostOrderGetHeight(BinTree BT) {
if(BT){
const int HL = PostOrderGetHeight(BT->Left);
const int HR = PostOrderGetHeight(BT->Right);
const int MaxH = (HL>HR)?HL:HR;
return (MaxH+1);
} else {
return 0;
}
}
如果一個節點沒有其他left
或right
節點,則此分支的結尾,並返回0
。
讓我們逐步瀏覽一棵樹(A),其中根具有左(B)和右(C)節點,而其左節點具有左節點(D)。 所有其他分支均為NULL。
我們將A傳遞給PostOrderGetHeight
,后者在其兩個節點(B)和(C)上調用PostOrderGetHeight
。
當PostOrderGetHeight
上調用B,它調用PostOrderGetHeight
在其左側節點d,並在NULL(這是它的右節點)。
這在D上調用PostOrderGetHeight
,D在其兩個NULL節點上調用PostOrderGetHeight
。 請注意,對NULL調用PostOrderGetHeight
返回0。
在此調用中, PostOrderGetHeight(D)
,HL和HR設置為零。 因此,這有效地初始化了它們。 然后MaxH
設置為零,從而有效地對其進行初始化。 然后對PostOrderGetHeight(D)
的調用返回PostOrderGetHeight(D)
MaxH+1
,即1。
請記住, PostOrderGetHeight(D)
是由被稱為PostOrderGetHeight(B)
所以它得到這個答案1設置HL
為1 B的右支為NULL,因此HR
被設置為0, MaxH
被設置為1,所以PostOrderGetHeight(B)
返回2。
PostOrderGetHeight(A)
稱為PostOrderGetHeight(B)
和PostOrderGetHeight(C)
。 由於C有兩個NULL分支,調用PostOrderGetHeight(C)
返回1。這將設置HL
從返回2 PostOrderGetHeight(B)
和HR
從返回1 PostOrderGetHeight(C)
使得MaxH
設置為2。因此PostOrderGetHeight(A)
將返回3,即樹A的高度。
通用遞歸算法依賴於以下事實:二叉樹的高度大於其左,右子樹的高度加1。空樹的高度為0。
這是一種非常基本的遞歸。 平凡的情況是0,更復雜的情況取決於對問題的各個部分進行相同的處理,然后將它們組合在一起(平凡情況除外)!
這有點像說一堵磚牆的高度是指一磚的高度減去一堵磚牆再減去一堵,沒有一堵牆的高度為0。好的,這是一種瘋狂的測量牆的方法,但是在計算中並不少見!
BinTree
將是一個指針。 因此,如果BT
為NULL
(空樹)並且函數返回高度為零(直接跳轉到else return 0
), if(BT)
行將為false。
注意: return 0;
會在這里做。 無需else
因為if語句的兩端都將返回。
因此,現在您看一下if-true分支的細節。
HL = PostOrderGetHeight(BT->Left);
HR = PostOrderGetHeight(BT->Right);
MaxH = (HL>HR)?HL:HR;
return (MaxH+1);
HL
(表示左側的高度)是從節點到樹的左側的高度, HR
是右側的高度。
MaxH = (HL>HR)?HL:HR
使用三元運算符(如果表達式為內聯),如果HL>HR
則該表達式的值為HL
否則為HR
。 這給了我們左子樹和右子樹的最大高度。
return語句( return (MaxH+1);
)加1。
如評論中所述,最好省略:
int HL,HR, MaxH;
和寫
int HL = PostOrderGetHeight(BT->Left);
int HR = PostOrderGetHeight(BT->Right);
int MaxH = (HL>HR)?HL:HR;
在C99(1999年標准)之前,您需要在函數開始時聲明所有變量。 這使編譯器可以輕松確定需要多少堆棧。
但是,除非受制於施加該規則的編譯器,否則它不應成為首選樣式(甚至不是所有20世紀的編譯器都這樣做)。
它具有較低的可讀性,並冒着使用未初始化數據(例如未使用的數據塊)的風險,從而降低了安全性。
稍微模糊的是,它也可能阻止編譯器看到優化堆棧布局的機會。
簡而言之,我想知道這段代碼是為老式編譯器還是由舊定時器編寫的。 我不稱呼任何人為老朋友。 我在那些編譯器上編寫了C代碼。 這不是侮辱。
沒有提供BinTree
的定義,但它必須類似於:
typedef struct BinTree_tag;
typedef struct {
struct BinTree_tag *Left;
struct BinTree_tag *Right;
} *BinTree ;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.