高级数据结构 | 二叉树判定— 是否为?满二叉树、完全二叉树、二叉搜索树(BST树)、(后面待更新... ...)平衡二叉树、对称二叉树、子树、相同的树 ...


是否是满二叉树。

满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。并且,一个满二叉树的第K层,结点总数是(2^k) -1。

从数学上看,满二叉树的各个层的结点数形成一个首项为1,公比为2的等比数列。
1 、 2 、 4 、 8 、 16...   . . . {1、2、4、8、16 ...\ ... } 124816... ...,每一层的结点数为上上一层的2倍,并且
{ 前 n − 1 层 的 结 点 数 } = { 第 n 层 的 结 点 数 − 1 } \{前 n-1 层的结点数\} = \{第 n 层的结点数 - 1\} {n1}={n1}

F
A
B
E
C
D
G

使用层序遍历判断每层是否达到最大值。

bool IS_FULL_BinTree(struct BtNode* ptr)
{
	bool res = true;
	if (ptr == NULL) return res;	// 空树也是满二叉树
	std::queue<struct BtNode*> que;
	que.push(ptr); 
	int floor = 1;		// 层
	while (!que.empty())
	{
		int i = 0;		// 记录该层元素的个数
		while (!que.empty() && i < floor)
		{
			ptr = que.front(); que.pop();
			if (ptr->leftchild != NULL)
			{
				que.push(ptr->leftchild);
			}
			if (ptr->rightchild != NULL)
			{
				que.push(ptr->rightchild);
			}
			++i;
		}
		if (i < floor)	// 该层元素不够,树不满
		{
			res = false;
			break;
		}
		floor *= 2;
	}
	return res;
}

使用递归方法判断相当方便,只是执行效率要差得多。思路:左右子树皆为满二叉树且深度相同。

bool Is_Full_BinTee(struct BtNode* ptr)
{
	return (ptr == NULL) || (Is_Full_BinTee(ptr->leftchild) && Is_Full_BinTee(ptr->rightchild)
							&& GetDepth(ptr->leftchild) == GetDepth(ptr->rightchild));
}

是否是完全二叉树。

完全二叉树可以理解为满二叉树的一种特殊情况,可视为最后一层的结点从右至左连续缺省若干个结点。比如下面这棵树。

F
A
B
E
C
D
G
A
B
E
C
D

左边为一颗满二叉树,从它的最后一层缺省掉结点G、F之后就是一颗完全二叉树。并且一个满二叉树也是一个完全二叉树。

思路分析:观察下图中所有叶子结点。

F
A
B
E
C
D
G
A
B
E
C
D
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL
NULL

如果我们在遍历时,把二叉树中指向NULL的结点也遍历的话,图左的满二叉树按照层序遍历输出 : { A ,     B , E ⏟ 2 ,     C , D , F , G ⏟ 4 ,     N U L L , N U L L , N U L L , N U L L , N U L L , N U L L , N U L L , N U L L ⏟ 8 } {A,\ \ \ \underbrace{B,E}_{2},\ \ \ \underbrace{C,D,F,G}_{4},\ \ \ \underbrace{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}_{8}} A,   2 B,E,   4 C,D,F,G,   8 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL

图左的满二叉树按照层序遍历输出:
{ A ,     B , E ⏟ 2 ,     C , D , N U L L , N U L L ⏟ 4 ,     N U L L , N U L L , N U L L , N U L L ⏟ 4 } {A,\ \ \ \underbrace{B,E}_{2},\ \ \ \underbrace{C,D,NULL,NULL}_{4},\ \ \ \underbrace{NULL,NULL,NULL,NULL}_{4}} A,   2 B,E,   4 C,D,NULL,NULL,   4 NULL,NULL,NULL,NULL

我们可以发现,完全二叉树在层次遍历时,最后输出的内容为一连串不间断的 NULL

而如果是非完全二叉树就会出现如 { A , B , . . .   . . .   n u l l , . . .   . . . n u l l ⏟ n ∗ n u l l , N , n u l l , . . .   . . . n u l l ⏟ m ∗ n u l l ⏞ } {{A,B,...\ ...\ \overbrace{\underbrace{null,... \ ... null}_{n*null},N, \underbrace{null,...\ ... null}_{m*null}}}} A,B,... ... nnull null,... ...null,N,mnull null,... ...null 的情况。因为完全二叉树是由满二叉树从左至右连续缺省得到,因此,在最后的n个null结点中是不会突然出现有效结点的,如公式中的 N 结点。

使用层序遍历,检查队列中最后的元素是否为一串连续的NULL结点。

bool IS_Comp_BinTree(struct BtNode* ptr)
{
	bool res = true;
	if (ptr == NULL) return res;
	std::queue<struct BtNode*> que;
	que.push(ptr);
	while (!que.empty())
	{
		ptr = que.front(); que.pop();
		if (ptr == NULL)	// null开始
		{
			while (!que.empty())
			{
				ptr = que.front(); que.pop();
				if (ptr != NULL)	// 检查是否全为null
				{
					res = false;
					break;
				}
			}
		}else
		{
			que.push(ptr->leftchild);
			que.push(ptr->rightchild);
		}

	}
	return res;
}

是否是二叉搜索树

一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

力扣leetcode:98.验证二叉搜索树
力扣官方题解:验证二叉搜索树

中序遍历
对于二叉搜索树,中序遍历时所得到的结点是升序的。因此我们只需验证这一点就好了。

class Solution {
public:
    bool InOrder(TreeNode* root, long& pre) {
        if (root == NULL) {
            return true;
        }
        if (!InOrder(root->left, pre)) {	// 中序遍历,递归寻找左孩子
            return false;
        }
        if (root->val <= pre) {				// pre记录的是前一个结点的值
            return false;					
        }
        pre = root->val;					// 更新pre的值
        return InOrder(root->right, pre);	// 遍历右子树
    }

    bool isValidBST(TreeNode* root) {
        long pre = LONG_MIN;
        return InOrder(root, pre);
    }
};

作者:huwt
链接:https://leetcode-cn.com/problems/validate-binary-search-tree/solution/98-yan-zheng-er-cha-sou-suo-shu-zhong-xu-bian-li-w/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

值得注意的是,中序遍历BST树的结果是一个升序的序列,因此,我们使用pre记录前一个结点的值,只需要判断当前值是否大于pre即可。

维护最大最小值
借助辅助函数helper(),进行递归。采用分而治之的策略分别验证左子树 or 右子树是否为BST数。

class Solution {
public:
    bool helper(TreeNode* root, long min, long max) {
        if (root == NULL) {			// 空树也是BST树
            return true;
        }	// 如果是左子树,当前结点需要小于父节点,即 root->val < max,右子树则大于 root->val > min
        if (root->val <= min || root->val >= max) {
            return false;
        }		// 分治
        return helper(root->left, min, root->val) && helper(root->right, root->val, max);
    }

    bool isValidBST(TreeNode* root) {
        long min = LONG_MIN;
        long max = LONG_MAX;
        return helper(root, min, max);
    }
};

作者:huwt
链接:https://leetcode-cn.com/problems/validate-binary-search-tree/solution/98-yan-zheng-er-cha-sou-suo-shu-zhong-xu-bian-li-w/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以上引用自力扣的 98.验证二叉搜索树 题解。


后面先留着,以后更新 ... ...
是否是平衡二叉树

是否是对称二叉树

是否是一棵树的子树

两个二叉树是否相同

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值