题目:输入两颗二叉树A和B,判断B是不是A的子结构。二叉树节点定义如下:
struct BinaryTreeNode{
int m_nValue;
BinaryTreeNode *m_pLeft;
BinaryTreeNode *m_pRight;
};
思路:
① 二叉树的每个节点往下均是一个二叉树。使用两个函数,一个函数递归遍历二叉树节点,对于每一个节点,调用另一个判定函数判定是否匹配
② 注意,下图也是子结构:
编译环境:ArchLinux+Clang3.3,C++11
实现一:递归+判定
#include <iostream>
#include <cstring>
#include <cassert>
using namespace std;
struct BinaryTreeNode{
int m_nValue;
BinaryTreeNode *m_pLeft;
BinaryTreeNode *m_pRight;
};
/** 判断pRoot1是否直接匹配pRoot2 **/
bool match(BinaryTreeNode *pRoot1, BinaryTreeNode *pRoot2);
/** 判断pRoot1是否包含pRoot2 **/
bool HasSubTree(BinaryTreeNode *pRoot1, BinaryTreeNode *pRoot2)
{
bool ret = false;
if (pRoot1 && pRoot2) {
if (pRoot1->m_nValue == pRoot2->m_nValue) // 此句判断实际”多余”,可由match已包含此功能
ret = match(pRoot1, pRoot2);
if (!ret)
ret = HasSubTree(pRoot1->m_pLeft, pRoot2);
if (!ret)
ret = HasSubTree(pRoot1->m_pRight, pRoot2);
}
return ret;
}
bool match(BinaryTreeNode *pRoot1, BinaryTreeNode *pRoot2)
{
if (!pRoot2)
return true;
if (!pRoot1)
return false;
if (pRoot1->m_nValue != pRoot2->m_nValue) {
return false;
}
return match(pRoot1->m_pLeft, pRoot2->m_pLeft) && match(pRoot1->m_pRight, pRoot2->m_pRight);
}
/**
* 根据二叉树的“单”字符表示形式(形如"1(2,3(,4))")创建二叉树
* 区间:[start, end)
**/
BinaryTreeNode *createTree(const char *start, const char *end)
{
if (start >= end) {
return nullptr;
}
if (end - start == 1) {
return new BinaryTreeNode{*start-'0', nullptr, nullptr};
}
const char *start1 = start+2;
const char *end1 = start+2;
int cnt = 0;
while (true) {
if (*end1 == '(') cnt++;
if (*end1 == ')') cnt--;
if (*end1 == ',' && cnt == 0) break;
end1++;
}
const char *start2 = end1+1;
const char *end2 = end1+1;
cnt = 0;
while (true) {
if (*end2 == '(') cnt++;
if (*end2 == ')' && cnt == 0) break;
if (*end2 == ')') cnt--;
end2++;
}
return new BinaryTreeNode{*start-'0',
createTree(start1, end1),
createTree(start2, end2)};
}
/** 打印二叉树 **/
void printTree(BinaryTreeNode *pRoot){
if (!pRoot) return;
cout << pRoot->m_nValue;
if (pRoot->m_pLeft || pRoot->m_pRight) cout << '(';
if (pRoot->m_pLeft) {
printTree(pRoot->m_pLeft);
}
if (pRoot->m_pLeft && pRoot->m_pRight) cout << ',';
if (pRoot->m_pRight) {
printTree(pRoot->m_pRight);
}
if (pRoot->m_pLeft || pRoot->m_pRight) cout << ')';
}
int main()
{
/** 构造二叉树 **/
const char *root = "8(8(9,2(4,7)),7)";
const char *root2 = "8(9,2)";
const char *root3 = "8(1,2)";
BinaryTreeNode *pRoot = createTree(root, root+strlen(root));
BinaryTreeNode *pRoot2 = createTree(root2, root2+strlen(root2));
BinaryTreeNode *pRoot3 = createTree(root3, root3+strlen(root3));
/** 打印 **/
printTree(pRoot); cout << endl;
printTree(pRoot2); cout << endl;
printTree(pRoot3); cout << endl;
/** 验证 **/
assert(HasSubTree(pRoot, pRoot2) == true);
assert(HasSubTree(pRoot, pRoot3) == false);
cout << "OK!" << endl;
}