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. 相關推薦

    輕鬆面試題目

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

    輕鬆面試的紅黑問題

       連續兩次面試都問到了紅黑樹,關鍵兩次都沒有答好,這次就完整地來學習整理一下。 沒有學習過紅黑樹的同學請參考: <<Introduction to Algorithms>> Chapter 13 Red-Black Trees Cha

    面試題——輕鬆面試的紅黑問題

     連續兩次面試都問到了紅黑樹,關鍵兩次都沒有答好,這次就完整地來學習整理一下。沒有學習過紅黑樹的同學請參考:<<Introduction to Algorithms>> Chapter 13 Red-Black Trees Chapter 14 Aug

    面試的連結串列題目(Java實現)

    本文轉載自:https://www.jianshu.com/p/a64d1ef95980這是一篇關於連結串列的文章,總結了連結串列資料結構和演算法相關的一些題目。先上鍊表的資料結構:class ListNode { ListNode next; int val; ListNode(in

    面試大總結之一:Java面試的連結串列題目

    連結串列是面試中常出現的一類題目,本文用Java實現了面試中常見的連結串列相關題目。本文主要參考整合重寫了《輕鬆搞定面試中的連結串列題目》和 《演算法大全(1)單鏈表》兩篇大作。兩篇大神的實現分別是C和C#,因為我更喜歡用Java面試,所以用Java重寫了所有實現,並附上自己

    一篇文章面試的連結串列題目(java實現)

    連結串列的資料結構 class ListNode { ListNode next; int val; ListNode(int x){ val = x; next = null;

    轉載 輕松面試題目

    相同 tree otp article ref position too -c rri 版權所有,轉載請註明出處,謝謝!http://blog.csdn.net/walkinginthewind/article/details/7518888 樹是一種比較重要的數據結構,尤

    面試題目(Java實現)

    本文轉載自:https://www.jianshu.com/p/0190985635eb這是一篇關於二叉樹的文章,總結了二叉樹資料結構和演算法的相關題目。先上二叉樹的資料結構:class TreeNode{ int val; //左孩子 TreeNode left; //右孩子

    面試大總結之:Java面試題目

    這是本系列的第二篇,與前一篇 面試大總結之一:Java搞定面試中的連結串列題目 相比,二叉樹的題目可以變化的就更多了。本文還是參考整合重寫了《輕鬆搞定面試中的二叉樹題目》和《演算法大全(3) 二叉樹》兩篇大作。本文一個小亮點就是幾乎每一道題都用了遞迴和迭代兩種方法寫過一遍

    一篇文章面試題目(java實現)

    結構 cer dea mat lastcomm ++ mir let balanced 最近總結了一些數據結構和算法相關的題目,這是第一篇文章,關於二叉樹的。 先上二叉樹的數據結構: class TreeNode{ int val; //左孩子 Tr

    面試39---的深度

    close none targe closed class display www opened ret 題目鏈接 求解二叉樹的深度,延伸可見leetcode110題。 法一:dfs。 1 private int TreeDepth(TreeNode root)

    LeetCode遍歷問題

    前置知識 二叉樹遍歷的相關知識, 可以參考我的另外一篇二分搜尋樹的博文,地址如下: https://blog.csdn.net/love905661433/article/details/82981527 前序遍歷 LeetCode-144. 二叉樹的前序遍歷 題目

    輕鬆RabbitMQ()——工作佇列之訊息分發機制

           上一篇博文中簡單介紹了一下RabbitMQ的基礎知識,並寫了一個經典語言入門程式——HelloWorld。本篇博文中我們將會建立一個工作佇列用來在工作者(consumer)間分發耗時任務。同樣是翻譯的官網例項。 工作佇列        在前一篇博文中,我們完

    NHN面試遍歷

    前不久去NHN公司參加面試,如網上形容的那樣,比賽和麵試的難道都相當高,最終沒有通過,當時有道題目還是挺有意思的,下來後,想了一段時間,想到了一種方法。 題目:使用程式遍歷二叉樹,按照深度來訪問二叉樹節點,如: 要求的訪問順序是1 2  3  4  5 6 使用一個A

    Java原來還可以這麼學:如何面試必考的集合類

    ![副本_未命名.jpg](https://upload-images.jianshu.io/upload_images/5447660-158639165ee1f96e.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 原創宣告 本文作

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

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

    [演算法總結] 20 道題 BAT 面試——

    本文首發於我的個人部落格:尾尾部落 0. 幾個概念 完全二叉樹:若二叉樹的高度是h,除第h層之外,其他(1~h-1)層的節點數都達到了最大個數,並且第h層的節點都連續的集中在最左邊。想到點什麼沒?實際上,完全二叉樹和堆聯絡比較緊密哈~~~ 滿二叉樹:除最後一層外,每一層上的所有節點都有兩個子節點,最後一層

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

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

    輕鬆面試題

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

    Java面試最基礎的演算法:氣泡排序演算法和遍歷

    首先是冒泡需要演算法,氣泡排序是所有的演算法最最基礎的演算法,一般人只是知道思路,但是真正的敲程式碼不一定能敲出來; 氣泡排序玩以後,使得陣列的數安從小到大的順序排列出來; 氣泡排序演算法: public void BuddleSort(){ public st