1. 程式人生 > >輕鬆搞定二叉樹面試題

輕鬆搞定二叉樹面試題

樹是一種比較重要的資料結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。二叉樹是遞迴定義的,因此,與二叉樹有關的題目基本都可以用遞迴思想解決,當然有些題目非遞迴解法也應該掌握,如非遞迴遍歷節點等等。本文努力對二叉樹相關題目做一個較全的整理總結,希望對找工作的同學有所幫助。

二叉樹節點定義如下:
struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode* m_pLeft;
    BinaryTreeNode* m_pRight;
};

題目列表:

詳細解答


遞迴解法:
(1)如果二叉樹為空,節點個數為0
(2)如果二叉樹不為空,二叉樹節點個數 = 左子樹節點個數 + 右子樹節點個數 + 1
參考程式碼如下:

  1. int GetNodeNum(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL) // 遞迴出口
  4.         return 0;  
  5.     return GetNodeNum(pRoot->m_pLeft) + GetNodeNum(pRoot->m_pRight) + 1;  
  6. }  

遞迴解法:

(1)如果二叉樹為空,二叉樹的深度為0
(2)如果二叉樹不為空,二叉樹的深度 = max(左子樹深度, 右子樹深度) + 1
參考程式碼如下:
  1. int GetDepth(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL) // 遞迴出口
  4.         return 0;  
  5.     int depthLeft = GetDepth(pRoot->m_pLeft);  
  6.     int depthRight = GetDepth(pRoot->m_pRight);  
  7.     return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);   
  8. }  

前序遍歷遞迴解法:
(1)如果二叉樹為空,空操作
(2)如果二叉樹不為空,訪問根節點,前序遍歷左子樹,前序遍歷右子樹
參考程式碼如下:
  1. void PreOrderTraverse(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL)  
  4.         return;  
  5.     Visit(pRoot); // 訪問根節點
  6.     PreOrderTraverse(pRoot->m_pLeft); // 前序遍歷左子樹
  7.     PreOrderTraverse(pRoot->m_pRight); // 前序遍歷右子樹
  8. }  
中序遍歷遞迴解法
(1)如果二叉樹為空,空操作。
(2)如果二叉樹不為空,中序遍歷左子樹,訪問根節點,中序遍歷右子樹
參考程式碼如下:
  1. void InOrderTraverse(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL)  
  4.         return;  
  5.     InOrderTraverse(pRoot->m_pLeft); // 中序遍歷左子樹
  6.     Visit(pRoot); // 訪問根節點
  7.     InOrderTraverse(pRoot->m_pRight); // 中序遍歷右子樹
  8. }  
後序遍歷遞迴解法
(1)如果二叉樹為空,空操作
(2)如果二叉樹不為空,後序遍歷左子樹,後序遍歷右子樹,訪問根節點
參考程式碼如下:
  1. void PostOrderTraverse(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL)  
  4.         return;  
  5.     PostOrderTraverse(pRoot->m_pLeft); // 後序遍歷左子樹
  6.     PostOrderTraverse(pRoot->m_pRight); // 後序遍歷右子樹
  7.     Visit(pRoot); // 訪問根節點
  8. }  

相當於廣度優先搜尋,使用佇列實現。佇列初始化,將根節點壓入佇列。當佇列不為空,進行如下操作:彈出一個節點,訪問,若左子節點或右子節點不為空,將其壓入佇列。

  1. void LevelTraverse(BinaryTreeNode * pRoot)  
  2. {  
  3.     if(pRoot == NULL)  
  4.         return;  
  5.     queue<BinaryTreeNode *> q;  
  6.     q.push(pRoot);  
  7.     while(!q.empty())  
  8.     {  
  9.         BinaryTreeNode * pNode = q.front();  
  10.         q.pop();  
  11.         Visit(pNode); // 訪問節點
  12.         if(pNode->m_pLeft != NULL)  
  13.             q.push(pNode->m_pLeft);  
  14.         if(pNode->m_pRight != NULL)  
  15.             q.push(pNode->m_pRight);  
  16.     }  
  17.     return;  
  18. }  
要求不能建立新節點,只調整指標。
遞迴解法:
(1)如果二叉樹查詢樹為空,不需要轉換,對應雙向連結串列的第一個節點是NULL,最後一個節點是NULL
(2)如果二叉查詢樹不為空:
如果左子樹為空,對應雙向有序連結串列的第一個節點是根節點,左邊不需要其他操作;
如果左子樹不為空,轉換左子樹,二叉查詢樹對應雙向有序連結串列的第一個節點就是左子樹轉換後雙向有序連結串列的第一個節點,同時將根節點和左子樹轉換後的雙向有序鏈 表的最後一個節點連線;
如果右子樹為空,對應雙向有序連結串列的最後一個節點是根節點,右邊不需要其他操作;
如果右子樹不為空,對應雙向有序連結串列的最後一個節點就是右子樹轉換後雙向有序連結串列的最後一個節點,同時將根節點和右子樹轉換後的雙向有序連結串列的第一個節點連 接。
參考程式碼如下:
  1. /****************************************************************************** 
  2. 引數: 
  3. pRoot: 二叉查詢樹根節點指標 
  4. pFirstNode: 轉換後雙向有序連結串列的第一個節點指標 
  5. pLastNode: 轉換後雙向有序連結串列的最後一個節點指標 
  6. ******************************************************************************/
  7. void Convert(BinaryTreeNode * pRoot,   
  8.              BinaryTreeNode * & pFirstNode, BinaryTreeNode * & pLastNode)  
  9. {  
  10.     BinaryTreeNode *pFirstLeft, *pLastLeft, * pFirstRight, *pLastRight;  
  11.     if(pRoot == NULL)   
  12.     {  
  13.         pFirstNode = NULL;  
  14.         pLastNode = NULL;  
  15.         return;  
  16.     }  
  17.     if(pRoot->m_pLeft == NULL)  
  18.     {  
  19.         // 如果左子樹為空,對應雙向有序連結串列的第一個節點是根節點
  20.         pFirstNode = pRoot;  
  21.     }  
  22.     else
  23.     {  
  24.         Convert(pRoot->m_pLeft, pFirstLeft, pLastLeft);  
  25.         // 二叉查詢樹對應雙向有序連結串列的第一個節點就是左子樹轉換後雙向有序連結串列的第一個節點
  26.         pFirstNode = pFirstLeft;  
  27.         // 將根節點和左子樹轉換後的雙向有序連結串列的最後一個節點連線
  28.         pRoot->m_pLeft = pLastLeft;  
  29.         pLastLeft->m_pRight = pRoot;  
  30.     }  
  31.     if(pRoot->m_pRight == NULL)  
  32.     {  
  33.         // 對應雙向有序連結串列的最後一個節點是根節點
  34.         pLastNode = pRoot;  
  35.     }  
  36.     else
  37.     {  
  38.         Convert(pRoot->m_pRight, pFirstRight, pLastRight);  
  39.         // 對應雙向有序連結串列的最後一個節點就是右子樹轉換後雙向有序連結串列的最後一個節點
  40.         pLastNode = pLastRight;  
  41.         // 將根節點和右子樹轉換後的雙向有序連結串列的第一個節點連線
  42.         pRoot->m_pRight = pFirstRight;  
  43.         pFirstRight->m_pLeft = pRoot;  
  44.     }  
  45.     return;  
  46. }  

遞迴解法:
(1)如果二叉樹為空或者k<1返回0
(2)如果二叉樹不為空並且k==1,返回1
(3)如果二叉樹不為空且k>1,返回左子樹中k-1層的節點個數與右子樹k-1層節點個數之和
參考程式碼如下:
  1. int GetNodeNumKthLevel(BinaryTreeNode * pRoot, int k)  
  2. {  
  3. 相關推薦

    輕鬆試題

    樹是一種比較重要的資料結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。二叉樹是遞迴定義的,因此,與二叉樹有關的題目基本都可以用遞迴思想解決

    JAVA 資料結構-輕鬆的面試題目

    樹是一種比較重要的資料結構,尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之分,其次序不能任意顛倒。二叉樹是遞迴定義的,因此,與二叉樹有關的題目基本都可以用遞迴思想解決,當

    面試總結:用Java方面的試題

    package org.hunan.guan.javaIO; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List

    重建——試題6《劍指offer》

    題目描述:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。  /** * Def

    試題的遍歷方式

    一、基本概念 1、二叉樹的概念 一棵二叉樹是結點的一個有限集合,該集合或者為空,或者是由一個根節點加上兩棵分別稱為左子樹和右子樹的二叉樹組成(即一個根節點最多隻有兩個孩子結點)。 2、二叉樹的特點 (1)每個結點最多有兩棵子樹,即二叉樹不存在度大於2的結

    試題(一)---判斷兩個結構是否相同

    一、首先這個問題是判斷二叉樹的結構是否相同,所以這就和二叉樹的資料的值無關。只需要判斷結構;判斷兩個二叉樹的結構是否相同很簡單。 採用遞迴的思想: (1)如果兩棵二叉樹都為空,返回真 (2)

    試題總結(Java)

    本文參考部落格:http://www.jianshu.com/p/0190985635eb 先上二叉樹的資料結構: class TreeNode{ int val; //左孩子 TreeNode left; //右孩子 TreeNo

    試題--已知的兩種遍歷序列,求出另一種遍歷序列

    已知先序遍歷序列和中序遍歷序列,求出後序序列   或者   已知中序序列和後序序列 , 求出先序遍歷。。都是一些考試中容易考的題目。 經過研究發現,已知先序序列和後序序列,無法唯一確定一棵樹,所以就無

    試題

    import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.uti

    常見的試題

        面試中,最常見是資料結構就是二叉樹和連結串列了,其中和二叉樹有關的常見面試題主要是:樹的前序遍歷、中序遍歷、後序遍歷、分層遍歷、樹的節點數、樹的葉子節點數、樹的第K層節點數、樹的深度、樹的寬度、平衡二叉樹的判定、完全二叉樹的判定、滿二叉樹的判定、由前序中序反推後序遍

    試題

    1. 前序/中序/後序遍歷(非遞迴) 前序 void PrevOrderNonR() { stack<Node*> s; Node* cur =

    【資料結構】---------試題(具體的所有實現)

    實現二叉樹的相關的操作: 先序遍歷樹(遞迴) 中序遍歷樹(遞迴) 後序遍歷樹(遞迴) 層序遍歷樹 建立一棵樹 樹的銷燬 樹的拷貝 二叉樹中節點的個數 二叉樹葉子節點的個數 二叉樹第K層節點的個數 樹的高度 在二叉樹中查詢節點 找當前節點的左子樹

    【資料結構】試題總結

    為了對二叉樹的知識進行鞏固,今天我們來解析5道二叉樹的經典面試題。 這五道面試題如下: 求二叉樹中最遠兩個結點的距離; 判斷一棵樹是否是完全二叉樹; 由前序和中序遍歷序列重建二叉樹 (前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6

    試題:前中序求後序、中後序求前序

    在面試時,避免不了的會遇到一些資料結構的面試題,今天我們就來了解一下二叉樹的經典面試題: 已知二叉樹的前序遍歷順序為ABCDEGHF,中序遍歷順序為DBAGEHCF,求該二叉樹的後序遍歷。 還有: 已知二叉樹的中序遍歷順序為DBAGEHCF,後序遍歷順序為DBGHEFCA,求該二叉樹的前序遍歷。 類似

    【java 資料結構】還不會?一篇

    二叉樹是我們常見的資料結構之一,在學習二叉樹之前我們需要知道什麼是樹,什麼是二叉樹,本篇主要講述了二叉樹,以及二叉樹的遍歷。 你能get到的知識點? 1、樹的介紹 2、二叉樹的介紹 3、二叉樹遍歷的四種方法 4、牛客題目:反轉二叉樹 目錄你能get到的知識點?一、知識預備1、樹2、樹的相關術語介紹1、二叉樹2

    幾分鐘排序的刪除節點演算法漫談無程式碼

    我希望看到我這部落格的時候是已經對應生成二叉排序樹演算法已經很熟悉了, 刪除節點的時候 也許我們會刪除20那個節點,那麼我們只需要把30節點的左子指標域設定null, 然後釋放節點20的記憶體地址,如果想得到被刪節點的資料可以返回, 這種節點是葉子節

    C++試題

    else 子節點 typename data fad pub struct char s[] 前序遍歷 #include <iostream> #include <stack> #include <queue> usi

    資料結構與演算法隨筆之------的遍歷(一文的四種遍歷)

    二叉樹的遍歷 二叉樹的遍歷(traversing binary tree)是指從根結點出發,按照某種次序依次訪問二叉樹中所有的結點,使得每個結點被訪問依次且僅被訪問一次。 遍歷分為四種,前序遍歷,中序遍歷,後序遍歷及層序遍歷 前序 中

    MySQL資料庫】試題整理

    本文記錄面試中經常問到的與網路協議相關的面試題。持續更新....... 先搭個模組架子,後面慢慢記錄! 事務的隔離級別 具體講解:https://blog.csdn.net/pcwl1206/article/details/84478127 1、讀未提交  READ

    網路協議】試題整理

    本文記錄面試中經常問到的與網路協議相關的面試題。持續更新....... 先搭個模組架子,後面慢慢記錄!   三次握手 TCP報文段首部格式: 序號:本報文段所傳送的資料的第一個位元組的序號; 確認號ack:期待收到對方下一個報文段的第一個資料位元組的序號