一个二叉树是否包含另一个二叉树


1、问题描述

二叉树A和B的每个节点的数据(int型数据)存储在不同文件中,存储方式为前序遍历和中序遍历,根据这两种遍历重建二叉树,并且判断二叉树A是否包含二叉树B。

1、算法描述

(1)首先将节点数据的前序遍历和中序遍历序列读入数组

(2)分别根据各自的前序遍历和中序遍历重建二叉树A和B

(3)判断B是否在A中

代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
#include <stack>

using namespace std;

enum COMMON_SIZE
{
 BUF_MAX_SIZE = 1024,
 MAX_NUM_LEN = 10,
};


enum ERROR_VALUE
{
 INPUT_PARAM_ERROR = -1,
 OPEN_FILE_ERROR = -2,
 FILE_NOT_EXSIT = -3,
 FILE_IS_EMTPY = -4,
 ALLOCA_FAILURE = -5,
 REBUILD_BTREE_ERROR = -6,
 NUM_OVERFLOW_ERROR = -7,
};

typedef struct BTreeNode_t_{
 int m_nValue;
 struct BTreeNode_t_ *m_pLeft;
 struct BTreeNode_t_ *m_pRight;
} BTreeNode_t;

void release_btree( BTreeNode_t *pRoot){
 if( pRoot == NULL )
  return;

 if( pRoot->m_pLeft )
  release_btree( pRoot->m_pLeft);
 if( pRoot->m_pRight)
  release_btree( pRoot->m_pRight);

 free(pRoot);
 pRoot = NULL;
 return;
}


BTreeNode_t * reconstruct_btree_by_preinorder( int *pPreOrder, int *pInOrder, int tree_nodes_total){
 if( pPreOrder == NULL || pInOrder == NULL ){
  fprintf(stderr, "ERROR: while construct btree by preinorder\n");
  return NULL;
 } 
 

 int m_nValue = pPreOrder[0];
 int root_data_index = -1;
 int i = 0;
 for( i = 0; i < tree_nodes_total; ++i ){
  if( pPreOrder[0] == pInOrder[i] ){
   root_data_index = i;
   break;
  }
 }

 if( root_data_index == -1 ){
  fprintf(stderr, "note: pPreOrder[0] is %d, pInOrder[0] is %d\n",
   pPreOrder[0], pInOrder[0]);
  fprintf(stderr, "note: root_data_index is -1, total nodes: %d\n", tree_nodes_total);
  return NULL;
 }

 BTreeNode_t *pRoot = NULL;
 pRoot = (BTreeNode_t *) malloc( sizeof( BTreeNode_t ));
 if( pRoot == NULL ){
  fprintf(stderr, "ERROR: can't alloca btree node: %d\n", m_nValue);
  return NULL;
 }

 pRoot->m_nValue = m_nValue;
 pRoot->m_pLeft = NULL;
 pRoot->m_pRight = NULL;

 int left_tree_len = root_data_index;
 int right_tree_len = tree_nodes_total - left_tree_len - 1;
 int *pleft_preorder = pPreOrder + 1;
 int *pright_preorder = pPreOrder + 1 + left_tree_len;
 int *pleft_inorder = pInOrder;
 int *pright_inorder = pInOrder + left_tree_len + 1;

 if( left_tree_len > 0 )
 {
  pRoot->m_pLeft = reconstruct_btree_by_preinorder( pleft_preorder, pleft_inorder, left_tree_len);
  if( pRoot->m_pLeft == NULL ){
   fprintf(stderr, "ERROR: failure to rebuild leftree, now release data: %d\n",
    m_nValue);
   release_btree( pRoot);
   pRoot = NULL;
   return NULL;
  }
 }

 if( right_tree_len > 0 ){
  pRoot->m_pRight = reconstruct_btree_by_preinorder( pright_preorder, pright_inorder, right_tree_len );
  if( pRoot->m_pRight == NULL ){
   fprintf(stderr, "ERROR: failure to right tree, now release data: %d\n",
    m_nValue);
   release_btree( pRoot );
   pRoot = NULL;
   return NULL;
  }
 }

 return pRoot;
}


int get_traver_data( char *buf, int *pOrder, int *order_len ){
 if( buf == NULL || pOrder == NULL ){
  return INPUT_PARAM_ERROR;
 }

 char *ptr = buf;
 char *pNumStart = ptr;
 int i = 0;
 int numLen = 0;
 int get_no_num = 0;
 int flag = 0;
 fprintf(stderr, "note: now enter get_traver_data()\n");
 while( *ptr != '\0' ){
  if( ( *ptr >= '0' ) && ( *ptr <= '9') ){
   ++numLen;
  } else  if( *ptr == ' ' ){
   *ptr = '\0';
   if( numLen > 0 && numLen <= MAX_NUM_LEN ){
    pOrder[i] = atoi( ptr - numLen );
    fprintf(stderr, "note: num is: %d\n", pOrder[i]);
    ++i; 
   }
   else if ( numLen > MAX_NUM_LEN){
    flag = NUM_OVERFLOW_ERROR;
    break;
   }
   numLen = 0;
   
  } else{
   get_no_num = -1;
   break;
  }

  ++ptr;
 }
 if( numLen != 0 ){
  pOrder[i] = atoi( ptr - numLen);
  fprintf(stderr, "note: num is: %d\n", pOrder[i]);
 }

 if( get_no_num != 0 )
  return get_no_num;

 *order_len = i + 1;
 fprintf(stderr, "note: finish get_traver_data()\n");
 return flag;
}

 

int get_traverse_nodes( char * file_name, int **pPreOrder, int **pInOrder, int *tree_nodes_total ){
 if( file_name == NULL ){
  fprintf(stderr, "ERROR: file(%s), line(%d), input parameter error\n",
    __FILE__, __LINE__);
  return INPUT_PARAM_ERROR; 
 }

 if( access( file_name, F_OK ) != 0){
  fprintf(stderr, "ERROR: file(%s) not exsit\n", file_name);
  return FILE_NOT_EXSIT;
 }

 struct stat fstat;
 size_t file_size = -1;

 stat(file_name, &fstat);
 file_size = fstat.st_size;
 if( file_size == 0 ){
  fprintf(stderr, "ERROR: file(%s) is empty\n", file_name);
  return FILE_IS_EMTPY;
 }
 fprintf(stderr, "note: file size: %ld\n", fstat.st_size);

 char * buf = NULL;
 buf = (char *)malloc( (file_size + 1) * sizeof( char ));
 if( buf == NULL ){
  fprintf(stderr, "ERROR: alloca buffer failure\n");
  return ALLOCA_FAILURE;
 }

 FILE *input = fopen( file_name, "rb");
 if( input == NULL ){
  fprintf(stderr, "ERROR: can't open input file [%s]\n", file_name);
  free(buf);
  buf = NULL;
  return OPEN_FILE_ERROR;
 }

 int line_len = -1;
 int index = 0;
 int flag = 0;
 int fini_read = 0;
 int preorder_len = 0;
 int inorder_len = 0;
 while( fgets( buf, file_size , input) != NULL ){
  size_t buf_len = strlen( buf );
  if( buf[ buf_len - 1] == '\n' )
   buf[ buf_len - 1 ] = '\0';
  fprintf(stderr, "note: current line is: %s\n", buf);
  switch( index )
  {
   case 0 :
   {
    *pPreOrder = (int *) malloc( buf_len * sizeof( int ));
    if( *pPreOrder == NULL ){
     flag = -1;
     break;
    }
    fprintf(stderr, "note: finish to get pPreOrder\n");
    flag = get_traver_data( buf, *pPreOrder, &preorder_len);
    break; 
   }
   case 1 :
   {
    *pInOrder = (int *) malloc( buf_len * sizeof( int ));
    if( *pInOrder == NULL ){
     flag = -1;
     break;
    }
    fprintf(stderr, "note: finish to get pInOrder\n");
    flag = get_traver_data( buf, *pInOrder, &inorder_len );
    break;
   }
   default:
   {
    break;
   }
  }

  ++index;
  if( flag != 0 || index == 2)
   break;
 }
 if( (flag != 0 ) || ( preorder_len != inorder_len)){
  fprintf(stderr, "ERROR: flag is %d, preorder_len is %d, inorder_len is %d\n", flag, preorder_len, inorder_len);
  if( *pPreOrder ){
   free( *pPreOrder );
   *pPreOrder = NULL;
  }
  if( *pInOrder ){
   free( *pInOrder );
   *pInOrder = NULL;
  }
  flag = -1;
 }

 free( buf );
 buf == NULL;


 fclose( input );
 input = NULL;

 *tree_nodes_total = preorder_len;
 fprintf(stderr, "note: sucess finish get_traverse_nodes()\n");
 return flag; 
}

void print_btree( BTreeNode_t *pRoot){
 if( pRoot == NULL )
  return;
 stack< BTreeNode_t *> st;
 while( pRoot != NULL || !st.empty()){
  while( pRoot != NULL ){
   printf("preorder test: node data: %d\n", pRoot->m_nValue);
   st.push( pRoot);
   pRoot = pRoot->m_pLeft;
  }
 
  if( !st.empty()){
   pRoot = st.top();
   st.pop();
   pRoot = pRoot->m_pRight;
  }
 }

 return;
}

void pprint_btree( BTreeNode_t *pRoot){
 if( pRoot == NULL )
  return;

 fprintf(stderr, "preorder test: node: %d\n", pRoot->m_nValue);
 if( pRoot->m_pLeft )
  print_btree( pRoot->m_pLeft);
 if( pRoot->m_pRight)
  print_btree( pRoot->m_pRight);

 return;
}

int check_is_include_helper( BTreeNode_t *pRoot1, BTreeNode_t *pRoot2){
 if( pRoot1 == NULL || pRoot2 == NULL ){
  fprintf(stderr, "ERROR: in check_is_include_helper(), input param error\n");
  return INPUT_PARAM_ERROR;
 }

 stack <BTreeNode_t *> st1;
 stack <BTreeNode_t *> st2;
 int flag = 0;
 while( (pRoot1 != NULL || !st1.empty()) &&
  ( pRoot2 != NULL || !st2.empty()) ){
  while( pRoot1 != NULL && pRoot2 != NULL){
   printf("note: cur data: pRoot1->m_nValue: %d, pRoot2->m_nValue: %d\n",
    pRoot1->m_nValue, pRoot2->m_nValue);
   if( pRoot1->m_nValue != pRoot2->m_nValue){
    flag = -1;
    break;
   }
   st1.push( pRoot1);
   st2.push( pRoot2);
   pRoot1 = pRoot1->m_pLeft;
   pRoot2 = pRoot2->m_pLeft;
  }
  if( flag != 0 )
   break;
  if( !st1.empty() && !st2.empty()){
   pRoot1 = st1.top();
   st1.pop();
   pRoot2 = st2.top();
   st2.pop();
   pRoot1 = pRoot1->m_pRight;
   pRoot2 = pRoot2->m_pRight;
  }
 }

 if( pRoot2 != NULL || !st2.empty() ){
  flag = -1;
 }

 while( !st1.empty() ){
  st1.pop();
 }
 
 while( !st2.empty() ){
  st2.pop();
 }

 return flag;

 
}

int check_is_include( BTreeNode_t *pRoot1, BTreeNode_t *pRoot2){
 if( pRoot1 == NULL || pRoot2 == NULL ){
  fprintf(stderr, "ERROR: in check_is_include(), input param error\n");
  return INPUT_PARAM_ERROR;
 }

 stack <BTreeNode_t*> st;
 int flag = -1;
 while( pRoot1 != NULL || !st.empty()){
  while( pRoot1 != NULL){
   printf("note: now check node data: %d\n", pRoot1->m_nValue);
   if( check_is_include_helper( pRoot1, pRoot2) == 0 ){
    flag = 0;
    break;
   }
   st.push( pRoot1);
   pRoot1 = pRoot1->m_pLeft;
  }
  if( flag == 0)
   break;
  if( !st.empty() ){
   pRoot1 = st.top();
   st.pop();
   pRoot1 = pRoot1->m_pRight;
  }
 }
 
 while( !st.empty() )
  st.pop();

 return flag;
}

int
main( int argc, char ** argv){
 if( argc < 3 ){
  fprintf(stderr, "ERROR: file(%s), line(%d), input parameter error\n", __FILE__, __LINE__);
  return INPUT_PARAM_ERROR;
 }

 char *afile = argv[1];
 char *bfile = argv[2];

 int ret = 0;
 int *pPreOrder = NULL;
 int *pInOrder = NULL;
 BTreeNode_t *pRoot1 = NULL;
 BTreeNode_t *pRoot2 = NULL;
 int tree_nodes_total = 0;
 ret = get_traverse_nodes( afile, &pPreOrder, &pInOrder, &tree_nodes_total);
 if( ret != 0 || tree_nodes_total == 0){
  fprintf(stderr, "ERROR: failure to get tree nodes info from file(%s)\n", afile);
  goto end;
 }

 
 pRoot1 = reconstruct_btree_by_preinorder( pPreOrder, pInOrder, tree_nodes_total);
 if( pRoot1 == NULL ){
  fprintf(stderr, "ERROR: failure to rebuild btree from file(%s)\n", afile);
  ret = REBUILD_BTREE_ERROR;
  goto end;
 }
 
 free( pPreOrder );
 pPreOrder = NULL;
 free( pInOrder );
 pInOrder = NULL;

 print_btree( pRoot1 );

 ret = get_traverse_nodes( bfile, &pPreOrder, &pInOrder, &tree_nodes_total);
 if( ret != 0 || tree_nodes_total == 0){
  fprintf(stderr, "ERROR: failure to get tree nodes info from file(%s)\n", bfile);
  goto end;
 }
 
 pRoot2 = reconstruct_btree_by_preinorder( pPreOrder, pInOrder, tree_nodes_total);
 if( pRoot2 == NULL ){
  fprintf(stderr, "ERROR: failure to rebuild btree from file(%s)\n", bfile);
  ret = REBUILD_BTREE_ERROR;
  goto end;
 }
 
 print_btree( pRoot2);
#if 1
 ret = check_is_include( pRoot1, pRoot2);
 if( ret != 0 ){
  fprintf(stderr, "ERROR: failure to find b btree in a btree\n");
  goto end;
 }
#endif
 printf("NOTE: success to find b btree in a btree\n"); 

end:
 if( pPreOrder != NULL ){
  free(pPreOrder);
  pPreOrder = NULL;
 }
 
 if( pInOrder != NULL ){
  free( pInOrder );
  pInOrder = NULL;
 }

 if( pRoot1 )
  release_btree( pRoot1);

 if( pRoot2 )
  release_btree( pRoot2);

 return ret;
}

代码运行显示:

二叉树A:

                         1

                            2                          3

                4                  5       6                   7

        8

 

二叉树B:

                                       3

                             6               7

分别存放在aBTree.txt和bBTree.txt中

aBTree.txt:

 

bBTree.txt:

 

运行: 

./a.out   aBTree.txt    bBTree.txt

可以找到 

./a.out   aBTree.txt   aBTree.txt

找不到

二叉树的常见问题及其解决程序

【递归】二叉树的先序建立及遍历

在JAVA中实现的二叉树结构

【非递归】二叉树的建立及遍历

二叉树递归实现与二重指针

二叉树先序中序非递归算法

轻松搞定面试中的二叉树题目

本文永久更新链接地址:

相关内容