二叉树(16)---- 一个二叉树是否包含另一个二叉树

二叉树问题合集

2、问题描述

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

3、算法描述

(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

找不到

时间: 2024-10-30 21:21:27

二叉树(16)---- 一个二叉树是否包含另一个二叉树的相关文章

如何高效的检测一个数组是否包含某一个值

如何检测一个数组(未排序)是否包含一个指定的值?这在Java中是一个非常有用且常见的操作.这还是一个在stackoverflow投票最多的一个问题.在投票最多的答案中,有几种不同的方式来完成这个问题.但是时间复杂度存在很大的差异.下面,我将展示每个方法所花费的时间. 1.检测数组中是否包含某一个值的四种方式 1)使用List public static boolean useList(String[] arr, String targetValue) { return Arrays.asList

php如何判断一个字符串是否包含另一个字符串

来自1:http://blog.sina.com.cn/s/blog_8edc37a801016yha.html -------------------------------------------------------------------- 我觉得最简单的就是:(用这种最好,StrPos效率最高) strpos($a, $b) !== false 如果$a 中存在 $b,则为 true ,否则为 false. 用 !== false (或者 === false) 的原因是如果 $b 正

【包容】一个类可以包含另一个类的对象

当一个类中出现了另一个类的对象,这种现象我们叫做包容! #include <iostream> using namespace std; class A { public: A(){x=0;} A(int i){x=i;} void get(){cout<<x<<endl;;} ~A(){} private: int x; }; class B { public: B(){y=0;} B(int i,int j,int k):a(i),b(j){y=k;}//初始化赋值

sql 一个字段是否包含另一个字段

/* Navicat MySQL Data Transfer Source Server         : test Source Server Version : 50528 Source Host           : localhost:3306 Source Database       : test Target Server Type    : MYSQL Target Server Version : 50528 File Encoding         : 65001 Da

【LintCode】判断一个字符串是否包含另一个字符串的所有字符

问题描述: 比较两个字符串A和B,确定A中是否包含B中所有的字符.字符串A和B中的字符都是 大写字母. 样例 给出 A = "ABCD" B = "ACD",返回 true 给出 A = "ABCD" B = "AABC", 返回 false 注意事项 在 A 中出现的 B 字符串里的字符不需要连续或者有序. 问题分析: 实质上利用的是哈希表的思想.只有大写字母,一共26个,遍历A的时候,往里面压,遍历B的时候,往外边弹,如果

关于javascript中判断一个字符串是否包含另一个字符串

var temp = "hello,world"; if(temp.indexOf("hello") >= 0 ){       alert('temp中包含hello字符串');   }

判断一个字符串是否包含另一个字符串

if (iOS8) {//ios8以上的系统才能用这个方法,否则会报错 if ([str containsString:str1]) { NSLog(@"str包含str1"); } } 通用的方法: NSRange range = [str rangeOfString:str1]; if (range.location != NSNotFound) { NSLog(@"str包含str1"); }

JAVA中判断一个字符串是否包含另一个字符串

用indexOf()函数,不包含则返回-1,包含返回0: String str="ABC_001"; if(str.indexOf("ABC")!=-1){    System.out.println("包含"); } else{    System.out.println("不包含"); }

java中如何判断一个字符串是否包含另外一个字符串的方法

indexOf(String s)的使用,如果包含,返回的值是包含该子字符串在父类字符串中起始位置:如果不包含必定全部返回值为-1 package my_automation; public class z_test { public static void main(String[] args) { String test = "This is test for string"; System.out.println(test.indexOf("This"));

ES6--javascript判断一个字符串是否存在另一个字符串中

es5中我们经常使用indexof()方法来判断一个字符串是否包含另外一个字符串中. 如果存在则返回匹配到的第一个索引值.如果没有则返回 -1.所以,判断一个字符串是否包含另外一个字符串中只需要判断是否为-1就行.-1代表不存在. 例如: let str = 'Hello World!'; console.log(str.indexOf('H'));//0 str中"H"的出现的第一个索引为0 console.log(str.indexOf('o'));//4 str中"o&