資料結構面試之五—二叉樹的常見操作(遞迴實現部分)
題註:《面試寶典》有相關習題,但思路相對不清晰,排版有錯誤,作者對此參考相關書籍和自己觀點進行了重寫,供大家參考。
轉載請註明:http://blog.csdn.net/wojiushiwo987/article/category/1210932
五、二叉樹的基本操作(遞迴實現)
二叉樹是筆試、面試的重點,包括選擇題的題型之——求解前、中、後序的遍曆結果等。去年(2011秋季)的百度筆試試題就考察了二叉樹的後序遍曆的非遞迴實現。
筆者先就下面常考幾個題目就遞迴演算法的實現分析如下:
遞迴的核心就是遍曆完根節點後,再依次同樣的方法遞迴左孩子、右孩子節點,直到為空白為止!
1.中根遍曆
//中序:左->根->右[遞迴實現]
template<typename elemType> voidbinaryTreeType<elemType>::inorder(nodeType<elemType> *p) { if( p != NULL ) { inorder(p->llink); cout << p->info << " "; inorder(p->rlink); } }
2.先根遍曆
//前序:根->左->右[遞迴實現]
template<typename elemType> voidbinaryTreeType<elemType>::preorder(nodeType<elemType> *p) { if( p != NULL ) { cout << p->info << " "; preorder(p->llink); preorder(p->rlink); } }
3.後根遍曆
//後序:左->右->根[遞迴實現]
template<typename elemType> voidbinaryTreeType<elemType>::postorder(nodeType<elemType> *p) { if( p != NULL ) { postorder(p->llink); postorder(p->rlink); cout << p->info << " "; } }
4.//求樹的高度![遞迴實現]
//等於左右子樹的最大高度+1
template<typename elemType> intbinaryTreeType<elemType>::height(nodeType<elemType> *p) { if( p == NULL) { return 0; } else { return 1 + max( height(p->llink),height(p->rlink)); //加上根節點1層.. } } //輔助max template<typename elemType> int binaryTreeType<elemType>::max(int x, int y) { return ( x >= y ? x : y ); }
5./全部/節點數目統計[遞迴實現]
template<typename elemType> int binaryTreeType<elemType>::nodeCount(nodeType<elemType>*p) { if(p == NULL) { return 0; } else { return 1 + nodeCount(p->llink) +nodeCount(p->rlink); } }
6.//分葉節點數目[遞迴實現]
//葉子節點的特徵就是左右子樹為空白。
template<typename elemType> intbinaryTreeType<elemType>::leavesCount(nodeType<elemType> *p) { if(p == NULL) { return 0; } else if(p->llink == NULL && p->rlink ==NULL) { return 1; // } else { return leavesCount(p->llink) +leavesCount(p->rlink); } }
7.判定兩顆二叉樹是否相等
【思路】:逐個節點(從根節點開始)進行比對,可能出現二叉樹1自根節點左子樹與二叉樹2自根節點的右子樹完全一致的情況,或者反之,這種情況也視為兩顆二叉樹一致。
分為一下5種情況。
template<typename elemType> boolbinaryTreeType<elemType>::beTreesEqual(nodeType<elemType> *first,nodeType<elemType> *second) { bool isFirstTreeNull = (first == NULL); bool isSecondTreeNull = (second == NULL); //case1: 兩者不等. if(isFirstTreeNull != isSecondTreeNull) { return false; } //case2: 兩者都為非空. if(isFirstTreeNull == true &&isSecondTreeNull==true) { return true; } //case3: 兩者都非空,但兩者的節點值不等 //case4: 兩者都非空,但節點值相等,需要考慮左右分支的情況... if(!isFirstTreeNull && !isSecondTreeNull) { if(first->info != second->info) //節點值是否相等 { return false; } else { return((beTreesEqual(first->llink,second->llink) &&beTreesEqual(first->rlink,second->rlink)) ||(beTreesEqual(first->llink,second->rlink) &&beTreesEqual(first->rlink,second->llink))); }// }//end if return false; }
建議:
1.代碼不是目的,主要是分析問題的思路;
2.可以自己畫一個二叉樹的草圖結構,然後根據程式進行代碼走讀,而後理清思路,再寫出代碼才是王道!
3.上述方面,筆者也有欠缺,希望和大家交流探討!