最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

用C語言判斷一個二叉樹是否為另一個的子結(jié)構(gòu)

 更新時間:2015年08月11日 15:42:14   作者:zinss26914  
這篇文章主要介紹了用C語言判斷一個二叉樹是否為另一個的子結(jié)構(gòu),是數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)當(dāng)中的基礎(chǔ)知識,需要的朋友可以參考下

1、問題描述:

     如何判斷一個二叉樹是否是另一個的子結(jié)構(gòu)?
     比如:

        2
      /   \
     9    8
    / \    /
   2  3  5
  /
6

   有個子結(jié)構(gòu)是
   9
  / \
2  3

2、分析問題:
    有關(guān)二叉樹的算法問題,一般都可以通過遞歸來解決。那么寫成一個正確的遞歸程序,首先一定要分析正確遞歸結(jié)束的條件。

拿這道題來講,什么時候遞歸結(jié)束。

<1>第二個二叉樹root2為空時,說明root2是第一棵二叉樹的root1的子結(jié)構(gòu),返回true。

<2>當(dāng)root1為空時,此時root2還沒為空,說明root2不是root1的子結(jié)構(gòu),返回false。

<3>遞歸下面有兩種思路:

    方法一:現(xiàn)在root1中找結(jié)點(diǎn)值與root2的值相等的結(jié)點(diǎn),如果找到就判斷root2是不是這個結(jié)點(diǎn)開頭的子結(jié)構(gòu)。所以,首先IsSubTree()判斷。

    方法二:就是直接判斷,相同就遞歸判斷root2左右子樹是不是也是相應(yīng)的子結(jié)構(gòu)。如果值不相同,就分別遞歸到root1的左右子樹尋找。尤其要注意最后兩句遞歸的邏輯判斷。

3、習(xí)題實(shí)例

    題目描述:  
    輸入兩顆二叉樹A,B,判斷B是不是A的子結(jié)構(gòu)。 
    輸入: 
    輸入可能包含多個測試樣例,輸入以EOF結(jié)束。 
    對于每個測試案例,輸入的第一行一個整數(shù)n,m(1<=n<=1000,1<=m<=1000):n代表將要輸入的二叉樹A的節(jié)點(diǎn)個數(shù)(節(jié)點(diǎn)從1開始計數(shù)),m代表將要輸入的二叉樹B的節(jié)點(diǎn)個數(shù)(節(jié)點(diǎn)從1開始計數(shù))。接下來一行有n個數(shù),每個數(shù)代表A樹中第i個元素的數(shù)值,接下來有n行,第一個數(shù)Ki代表第i個節(jié)點(diǎn)的子孩子個數(shù),接下來有Ki個樹,代表節(jié)點(diǎn)i子孩子節(jié)點(diǎn)標(biāo)號。接下來m+1行,與樹A描述相同。 
    輸出: 
    對應(yīng)每個測試案例, 
    若B是A的子樹輸出”YES”(不包含引號)。否則,輸出“NO”(不包含引號)。 
    樣例輸入: 
    7 3 
    8 8 7 9 2 4 7 
    2 2 3 
    2 4 5 
    0 
    0 
    2 6 7 
    0 
    0 
    8 9 2 
    2 2 3 
    0 
    0 

    實(shí)現(xiàn)
    第一步,在A樹中查找和B樹根節(jié)點(diǎn)一樣的值,其實(shí)就是樹的前序遍歷,建議遞歸,方便(ps:非遞歸無非就是用個棧存儲結(jié)點(diǎn)而已,沒什么技術(shù)含量)

  

 /** 
   * 第一步判斷,遍歷A樹查找是否有等于B樹根結(jié)點(diǎn)的子樹 
   */ 
  int judgeChildTree(struct btree *ahead, int numa, struct btree *bhead, int numb) 
  { 
    int flag = 0; 
   
    if (numa != -1 && numb != -1) { 
      if (ahead[numa].value == bhead[numb].value) 
        flag = doesTree1HasTree2(ahead, numa, bhead, numb); 
   
      if (! flag && ahead[numa].lchild != -1) 
        flag = judgeChildTree(ahead, ahead[numa].lchild, bhead, numb); 
   
      if (! flag && ahead[numa].rchild != -1) 
        flag = judgeChildTree(ahead, ahead[numa].rchild, bhead, numb); 
    } 
   
    return flag; 
  } 

    第二步,進(jìn)一步判斷A中以R為根節(jié)點(diǎn)的子樹是不是與B樹具有相同的結(jié)點(diǎn)

  /** 
   * 第二步判斷,判斷A樹是否有B樹的子結(jié)構(gòu) 
   */ 
  int doesTree1HasTree2(struct btree *ahead, int numa, struct btree *bhead, int numb) 
  { 
    if (numb == -1)  
      return 1; 
    if (numa == -1) 
      return 0; 
   
    if (ahead[numa].value != bhead[numb].value) 
      return 0; 
   
    return (doesTree1HasTree2(ahead, ahead[numa].lchild, bhead, bhead[numb].lchild) && 
      doesTree1HasTree2(ahead, ahead[numa].rchild, bhead, bhead[numb].rchild)); 
  } 


完整代碼

   

 #include <stdio.h> 
  #include <stdlib.h> 
   
  // 二叉樹結(jié)點(diǎn)定義 
  struct btree 
  { 
    int value; 
    int lchild, rchild; 
  }; 
   
  // A樹和B樹的最多結(jié)點(diǎn)數(shù) 
  int n, m; 
   
  /** 
   * 第二步判斷,判斷A樹是否有B樹的子結(jié)構(gòu) 
   */ 
  int doesTree1HasTree2(struct btree *ahead, int numa, struct btree *bhead, int numb) 
  { 
    if (numb == -1)  
      return 1; 
    if (numa == -1) 
      return 0; 
   
    if (ahead[numa].value != bhead[numb].value) 
      return 0; 
   
    return (doesTree1HasTree2(ahead, ahead[numa].lchild, bhead, bhead[numb].lchild) && 
      doesTree1HasTree2(ahead, ahead[numa].rchild, bhead, bhead[numb].rchild)); 
  } 
   
  /** 
   * 第一步判斷,遍歷A樹查找是否有等于B樹根結(jié)點(diǎn)的子樹 
   */ 
  int judgeChildTree(struct btree *ahead, int numa, struct btree *bhead, int numb) 
  { 
    int flag = 0; 
   
    if (numa != -1 && numb != -1) { 
      if (ahead[numa].value == bhead[numb].value) 
        flag = doesTree1HasTree2(ahead, numa, bhead, numb); 
   
      if (! flag && ahead[numa].lchild != -1) 
        flag = judgeChildTree(ahead, ahead[numa].lchild, bhead, numb); 
   
      if (! flag && ahead[numa].rchild != -1) 
        flag = judgeChildTree(ahead, ahead[numa].rchild, bhead, numb); 
    } 
   
    return flag; 
  } 
   
  int main(void) 
  { 
    int i, data, count, left, right, flag; 
    struct btree *ahead, *bhead; 
   
    while (scanf("%d %d", &n, &m) != EOF) { 
      // 獲取A樹的節(jié)點(diǎn)值 
      ahead = (struct btree *)malloc(sizeof(struct btree) * n); 
      for (i = 0; i < n; i ++) { 
        scanf("%d", &data); 
        ahead[i].value = data; 
        ahead[i].lchild = ahead[i].rchild = -1; 
      } 
   
      for (i = 0; i < n; i ++) { 
        scanf("%d", &count); 
        if (count == 0) { 
          continue; 
        } else { 
          if (count == 1) { 
            scanf("%d", &left); 
            ahead[i].lchild = left - 1; 
          } else { 
            scanf("%d %d", &left, &right); 
            ahead[i].lchild = left - 1; 
            ahead[i].rchild = right - 1; 
          } 
        } 
      } 
   
      // 獲取B樹的節(jié)點(diǎn)值 
      bhead = (struct btree *)malloc(sizeof(struct btree) * m); 
      for (i = 0; i < m; i ++) { 
        scanf("%d", &data); 
        bhead[i].value = data; 
        bhead[i].lchild = bhead[i].rchild = -1; 
      } 
   
      for (i = 0; i < m; i ++) { 
        scanf("%d", &count); 
        if (count == 0) { 
          continue; 
        } else { 
          if (count == 1) { 
            scanf("%d", &left); 
            bhead[i].lchild = left - 1; 
          } else { 
            scanf("%d %d", &left, &right); 
            bhead[i].lchild = left - 1; 
            bhead[i].rchild = right - 1; 
          } 
        } 
      } 
   
      // 判斷B樹是否為A的子樹 
      if (n == 0 || m == 0) { 
        printf("NO\n"); 
        continue; 
      } 
   
      flag = judgeChildTree(ahead, 0, bhead, 0); 
      if (flag) 
        printf("YES\n"); 
      else 
        printf("NO\n"); 
   
      free(ahead); 
      free(bhead); 
    } 
   
    return 0; 
  } 

相關(guān)文章

  • 基于C++輸出指針自增(++)運(yùn)算的示例分析

    基于C++輸出指針自增(++)運(yùn)算的示例分析

    本篇文章是對C++中輸出指針自增(++)運(yùn)算的示例進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++ vector的用法小結(jié)

    C++ vector的用法小結(jié)

    這篇文章主要介紹了c++中,vector是一個十分有用的容器,下面對這個容器做一下總結(jié)
    2013-12-12
  • 簡介C/C++預(yù)處理器的一些工作

    簡介C/C++預(yù)處理器的一些工作

    這篇文章主要介紹了C/C++預(yù)處理器的一些工作,有助于理解編譯器底層的工作流程,需要的朋友可以參考下
    2015-07-07
  • Visual Studio C++指針靠前靠后的問題全面解析

    Visual Studio C++指針靠前靠后的問題全面解析

    這篇文章主要介紹了Visual Studio C++指針靠前靠后的問題全面解析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個鏈表是否相交

    C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個鏈表是否相交

    這篇文章主要介紹了C++將二叉樹轉(zhuǎn)為雙向鏈表及判斷兩個鏈表是否相交的方法,文中還給出了求兩個鏈表相交的第一個節(jié)點(diǎn)列的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2016-02-02
  • C/C++ 監(jiān)控磁盤與目錄操作的示例

    C/C++ 監(jiān)控磁盤與目錄操作的示例

    這篇文章主要介紹了C/C++ 監(jiān)控磁盤與目錄操作的示例,幫助大家更好的理解和學(xué)習(xí)C/C++編程,感興趣的朋友可以了解下
    2020-10-10
  • C++實(shí)現(xiàn)LeetCode(68.文本左右對齊)

    C++實(shí)現(xiàn)LeetCode(68.文本左右對齊)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(68.文本左右對齊),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言中實(shí)現(xiàn)協(xié)程案例

    C語言中實(shí)現(xiàn)協(xié)程案例

    這篇文章主要介紹了C語言中實(shí)現(xiàn)協(xié)程案例,本文通過將協(xié)程與線程和異步回調(diào)進(jìn)行對比,以及具體實(shí)現(xiàn)案例,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C/C++字節(jié)序的深入理解

    C/C++字節(jié)序的深入理解

    本文主要介紹了C/C++字節(jié)序的深入理解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 一文讓你徹底明白C++中的const

    一文讓你徹底明白C++中的const

    這篇文章主要給大家介紹了關(guān)于C++中const的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評論

恭城| 榕江县| 德安县| 吐鲁番市| 新邵县| 邵东县| 开化县| 石狮市| 连城县| 桃源县| 建宁县| 灯塔市| 二手房| 隆子县| 盖州市| 克拉玛依市| 宁远县| 灵丘县| 兴山县| 高淳县| 湄潭县| 通化市| 昆明市| 南汇区| 汉源县| 兴隆县| 洞口县| 通化县| 梁山县| 米脂县| 山东省| 滦南县| 清远市| 湾仔区| 陈巴尔虎旗| 宝鸡市| 如皋市| 汶上县| 花垣县| 古田县| 宁陵县|