二叉樹中節點的最大距離
阿新 • • 發佈:2019-01-24
問題定義
如果我們把二叉樹看成一個圖,父子節點之間的連線看成是雙向的,我們姑且定義"距離"為兩節點之間邊的個數。寫一個程式求一棵二叉樹中相距最遠的兩個節點之間的距離。
《程式設計之美》的解法
書中對這個問題的分析是很清楚的,我嘗試用自己的方式簡短覆述。
計算一個二叉樹的最大距離有兩個情況:
- 情況A: 路徑經過左子樹的最深節點,通過根節點,再到右子樹的最深節點。
- 情況B: 路徑不穿過根節點,而是左子樹或右子樹的最大距離路徑,取其大者。
只需要計算這兩個情況的路徑距離,並取其大者,就是該二叉樹的最大距離。
// 資料結構定義 struct NODE { NODE* pLeft; // 左子樹 NODE* pRight; // 右子樹 int nMaxLeft; // 左子樹中的最長距離 int nMaxRight; // 右子樹中的最長距離 char chValue; // 該節點的值 }; int nMaxLen = 0; // 尋找樹中最長的兩段距離 void FindMaxLen(NODE* pRoot) { // 遍歷到葉子節點,返回 if(pRoot == NULL) { return; } // 如果左子樹為空,那麼該節點的左邊最長距離為0 if(pRoot -> pLeft == NULL) { pRoot -> nMaxLeft = 0; } // 如果右子樹為空,那麼該節點的右邊最長距離為0 if(pRoot -> pRight == NULL) { pRoot -> nMaxRight = 0; } // 如果左子樹不為空,遞迴尋找左子樹最長距離 if(pRoot -> pLeft != NULL) { FindMaxLen(pRoot -> pLeft); } // 如果右子樹不為空,遞迴尋找右子樹最長距離 if(pRoot -> pRight != NULL) { FindMaxLen(pRoot -> pRight); } // 計算左子樹最長節點距離 if(pRoot -> pLeft != NULL) { int nTempMax = 0; if(pRoot -> pLeft -> nMaxLeft > pRoot -> pLeft -> nMaxRight) { nTempMax = pRoot -> pLeft -> nMaxLeft; } else { nTempMax = pRoot -> pLeft -> nMaxRight; } pRoot -> nMaxLeft = nTempMax + 1; } // 計算右子樹最長節點距離 if(pRoot -> pRight != NULL) { int nTempMax = 0; if(pRoot -> pRight -> nMaxLeft > pRoot -> pRight -> nMaxRight) { nTempMax = pRoot -> pRight -> nMaxLeft; } else { nTempMax = pRoot -> pRight -> nMaxRight; } pRoot -> nMaxRight = nTempMax + 1; } // 更新最長距離 if(pRoot -> nMaxLeft + pRoot -> nMaxRight > nMaxLen) { nMaxLen = pRoot -> nMaxLeft + pRoot -> nMaxRight; } }
這段程式碼有幾個缺點:
1、演算法在二叉樹結構體中加入了侵入式(intrusive)的變數nMaxLeft, nMaxRight
2、使用了全域性變數 nMaxLen。每次使用要額外初始化
3、邏輯比較複雜,也有許多 NULL 相關的條件測試
我的解法:根據最大距離的定義,遞迴求解
參考資料://return MaxDistance of t int MaxDistance(Tree * t) { if (t == 0) return 0; int lheight = height(t->left)-1;//-1:邊的數目=節點數目-1 int rheight = height(t->right)-1; int lDis = MaxDistance(t->left); int rDis = MaxDistance(t->right); return max(lheight + rheight + 2,max(lDis,rDis));//+2:根節點到左右孩子的邊 } //returns height of tree with root t int height(Tree * t){ if (t == 0) return 0; return 1 + max(height(t->left),height(t->right)); }