1. 程式人生 > >【C語言常識】二叉樹入門知識

【C語言常識】二叉樹入門知識

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

二叉樹節點定義如下:
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. 相關推薦

    C語言常識入門知識

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

    數據結構(c++)

    public ear ren fontsize tree fault left reorder 個數 頭文件: #include <iostream> using namespace std; template<class Type> cl

    算法模板

    treenode tor bsp res stack ack 算法 == oid 模板: 1.先序遍歷三種方法 1)叠代: class Solution { public: /** * @param root: The root of binary tr

    劍指offer——python第38題的深度

    描述 sub pan 節點 solution class oot 返回值 self. 題目描述 輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。 解題思路 想了很久。。首先本渣渣就不太理解遞歸在pyt

    劍指offer的下一個節點

    給出一棵二叉樹和一個節點,求中序遍歷序列的下一個節點。二叉樹結構是給出了左右節點以及父節點的。 首先分析中序遍歷,中序遍歷即左父右的順序遍歷樹。 分析規律: (1)節點存在右節點 if(p->right) 則不斷檢查p->right是否還有左節點,若沒有左節點了,該節點即

    C語言資料結構-、哈夫曼、佇列小練習

    原始碼地址 GitHub:https://github.com/GYT0313/C-DataStructure 1. 二叉樹 要求: 掌握二叉樹的二叉連結串列的建立方法; 掌握二叉樹的3種遍歷遞迴演算法; 掌握二叉樹的3種遍歷的非遞迴演算法。 程式

    劍指offer中和為某一值的路徑python

    題目描述 輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,陣列長度大的陣列靠前) 思路: 暴力遍歷二叉樹每一個節點,採用遞歸回溯的思想。建立一個全域性的re

    劍指offer的鏡像

    oot node 二叉樹 item 題目 左右子樹 font 交換 bottom 題目描述 操作給定的二叉樹,將其變換為源二叉樹的鏡像。 輸入描述: 二叉樹的鏡像定義:源二叉樹 8 / 6 10 / \

    劍指Offer的下一個結點

    題目描述:給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指標。 解題思路: 解題的時候要將情況考慮清楚,(1) 若一個結點有右子樹,那麼下一個結點就是右子樹中的最左子結點。 (2) 若沒有右子樹,則向上

    劍指offer的深度

    層次遍歷 執行時間:28ms 佔用記憶體:5752k # -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.

    資料結構之---C語言實現平衡(AVL

    //AVL(自動平衡二叉樹) #include <stdio.h> #include <stdlib.h> typedef int ElemType; //每個結點的平均值 typedef enum {      EH = 0,      LH =

    劍指offer中和為某一值的路徑

    題目描述:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。輸入:每個測試案例包括n+1行:第一行為2個整數n,

    劍指offer中和為某一值得路徑 java

    路徑為從根節點到葉節點一條路徑,路徑經過的各節點數值之和等於某一給定數值,則列印路徑上的節點 因為需要列印滿足條件的路徑節點資訊和各節點之和,需要棧記錄經過的節點,和一個儲存數值之和的變數用前序遍歷

    C語言建立一個

    如何建立一個二叉樹,先序遍歷,中序遍歷。 #include <stdio.h> #include <stdlib.h> #include<bits/stdc++.h&g

    資料結構 C語言 鏈式

    【問題描述】 採用二叉連結串列作為二叉樹的儲存結構實現各項功能 【任務要求】 (1) 輸入二叉樹的先序序列,建立二叉樹; (2) 用程式實現二叉樹的中序遍歷; (3) 編寫程式求二叉

    C語言遍歷的遞迴呼叫操作集

    #include <string.h>   #include <stdio.h>   #include <malloc.h>     typedef int ElemType;    typedef struct BiTNode  

    C語言版)遍歷演算法——包含遞迴前、中、後序和層次,非遞迴前、中、後序和層次遍歷共八種

    #include <stdlib.h> #include <stdio.h> #include "BiTree.h" #include "LinkStack.h" #include "LinkQueue.h" //初始化二叉樹(含根節點) void InitBiTree(pBiTr

    C語言:線索的線索化及其遍歷實現

           前序和中序遍歷都實現了,後序線索化還不是很明白!如有大神看到,望指正!不勝感激! // 中序線索二叉樹實現.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include<iostream> #includ

    劍指offer的深度python實現

    劍指offer題目:輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。思路:深度使用遞迴# -*- coding:utf-8 -*- # class TreeNode: # def __init__

    前綴思想中所有距離為 K 的結點

    right 前綴 amp add ger integer 思想 length 簡單 863. 二叉樹中所有距離為 K 的結點 class Solution { Map<TreeNode,String>map=new HashMap<>