1. 程式人生 > >求二叉樹深度以及尋找二叉樹中某一節點值

求二叉樹深度以及尋找二叉樹中某一節點值

求二叉樹的深度依然用的是二叉樹遞迴的特性。二叉樹的深度就是你根節點的這一層加上他左孩子或者右孩子中深度大的哪一個,同樣這也能被劃分為子問題。

size_t BTreeDepth(BTNode* root)
{
if (root == NULL)
return 0;
if (BTreeDepth(root->_left) > BTreeDepth(root->_right))
return 1 + BTreeDepth(root->_left);
else
return 1 + BTreeDepth(root->_right);
}


這裡需要多進行的一步是深度大小的判斷,讓1加上你左孩子或者右孩子深度大的那個,就需要比較兩個深度,當然這裡也可以用更簡單清晰的三步運算子來計算。
return (BTreeDepth(root->_left) > BTreeDepth(root->_right))? 1 + BTreeDepth(root->_left) :1 + BTreeDepth(root->_right);


(a > c) ? a : c 三步運算子是如果a>c 那麼執行a語句,如果不大於那就執行c語句。
第二個函式是查詢二叉樹中的某個資料,同樣是遞迴,但是你在寫的時候會遇到一個問題。
BTNode* BTreeFind(BTNode* root, BTDataType x)
{
if (root== NULL)
return NULL;
if (root->_data == x)
return root;
else
{
BTreeFind(root->_left, x);
BTreeFind(root->_right, x);
}
}


你運用遞迴寫出來的程式是這樣的,能執行嗎?你會發現有時候你的程式編譯沒有錯誤但是每次執行都會出錯誤不能正確輸出你要的東西
 
還拿之前這個圖來走一遍,假如你現在查詢的是3,進來1不為空,但是也不等於你找的3就開始往else裡邊的語句走,先走他的左孩子的遞迴,進來之後是2,不等於3,又開始往他的左孩子走,走到3發現等於3啊,這時候要返回root了,返回成功,這時候在root是2的函式中,往左子樹的遞迴已經結束了,開始走下一句,結果進入到了2的右孩子中,遇到4左右孩子是空那就開始返回空。
其實簡單的形容起來就是,你雖然找到了你的3但是函式並不知道你找到了,他還是會一直找下去,因為有兩種情況都會返回一種是找到了對應的值,一種是空,所以即使你找到了,最終返回的也不是你的返回值。那應該怎麼寫呢?你需要的是開始進入下一次遞迴之前判斷一下,你的上一層遞迴返回給你的地址是不是就是你要找的那個地方的地址,如果是那就不用再繼續走下去了,直接返回上一層遞迴給你返回的地址就可以了。
BTNode* BTreeFind(BTNode* root, BTDataType x)
{
BTNode *ret = NULL;
if (root == NULL)
return root;
if (root->_data == x)
return root;
else
{
ret = BTreeFind(root->_left, x);
if (ret != NULL)
{
if (ret->_data == x)
return ret;
}
ret = BTreeFind(root->_right, x);
}
return ret;
}


寫了之後有一系列的bug,很多時候ret都是空你是不能訪問他的data的,導致除錯了很多次才改成了現在一個目前沒有bug的程式,用ret來接受你上一層遞迴的返回值,來進行判斷,如果當前返回值已經等於你要找的數值的話,那就繼續返回這個返回值。但是一定要注意,在判斷ret的資料是不是你要找的資料之前一定要判斷一下你的ret當前是不是空,如果是的話不判斷繼續進行訪問就會出現記憶體出錯問題。個人認為這個函式還是需要動一些腦子來仔細思考一下各種情況的。