程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 用C說話斷定一個二叉樹能否為另外一個的子構造

用C說話斷定一個二叉樹能否為另外一個的子構造

編輯:關於C++

用C說話斷定一個二叉樹能否為另外一個的子構造。本站提示廣大學習愛好者:(用C說話斷定一個二叉樹能否為另外一個的子構造)文章只能為提供參考,不一定能成為您想要的結果。以下是用C說話斷定一個二叉樹能否為另外一個的子構造正文


1、成績描寫:

     若何斷定一個二叉樹能否是另外一個的子構造?
     好比:

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

   有個子構造是
   9
  / \
2  3

2、剖析成績:
    有關二叉樹的算法成績,普通都可以經由過程遞歸來處理。那末寫成一個准確的遞歸途序,起首必定要剖析准確遞歸停止的前提。

拿這道題來說,甚麼時刻遞歸停止。

<1>第二個二叉樹root2為空時,解釋root2是第一棵二叉樹的root1的子構造,前往true。

<2>當root1為空時,此時root2還沒為空,解釋root2不是root1的子構造,前往false。

<3>遞歸上面有兩種思緒:

    辦法一:如今root1中找結點值與root2的值相等的結點,假如找到就斷定root2是否是這個結點開首的子構造。所以,起首IsSubTree()斷定。

    辦法二:就是直接斷定,雷同就遞歸斷定root2閣下子樹是否是也是響應的子構造。假如值不雷同,就分離遞歸到root1的閣下子樹尋覓。特別要留意最初兩句遞歸的邏輯斷定。

3、習題實例

    標題描寫:  
    輸出兩顆二叉樹A,B,斷定B是否是A的子構造。 
    輸出: 
    輸出能夠包括多個測試樣例,輸出以EOF停止。 
    關於每一個測試案例,輸出的第一行一個整數n,m(1<=n<=1000,1<=m<=1000):n代表將要輸出的二叉樹A的節點個數(節點從1開端計數),m代表將要輸出的二叉樹B的節點個數(節點從1開端計數)。接上去一行有n個數,每一個數代表A樹中第i個元素的數值,接上去有n行,第一個數Ki代表第i個節點的子孩子個數,接上去有Ki個樹,代表節點i子孩子節點標號。接上去m+1行,與樹A描寫雷同。 
    輸入: 
    對應每一個測試案例, 
    若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 

    完成
    第一步,在A樹中查找和B樹根節點一樣的值,其實就是樹的前序遍歷,建議遞歸,便利(ps:非遞歸不過就是用個棧存儲結點罷了,沒甚麼技巧含量)

  

 /** 
   * 第一步斷定,遍歷A樹查找能否有等於B樹根結點的子樹 
   */ 
  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; 
  } 

    第二步,進一步斷定A中以R為根節點的子樹是否是與B樹具有雷同的結點

  /** 
   * 第二步斷定,斷定A樹能否有B樹的子構造 
   */ 
  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> 
   
  // 二叉樹結點界說 
  struct btree 
  { 
    int value; 
    int lchild, rchild; 
  }; 
   
  // A樹和B樹的最多結點數 
  int n, m; 
   
  /** 
   * 第二步斷定,斷定A樹能否有B樹的子構造 
   */ 
  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樹根結點的子樹 
   */ 
  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樹的節點值 
      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樹的節點值 
      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; 
  } 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved