检查一棵二叉树是否为二叉搜索树

本文介绍了一种检查二叉树是否为二叉搜索树的方法。关键在于利用递归方式检查每个节点是否符合二叉搜索树的定义:左子树的所有节点值小于根节点,右子树的所有节点值大于根节点,且没有重复节点。通过递归设置最大最小值进行判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

检查一颗二叉树是否为二叉搜索树

思路

首先,什么是二叉搜索树?

二叉搜索树左子树中任意节点值小于根节点;右子树中任意节点值大于根节点;左右子树都必须是二叉查找树,不允许存在重复节点

不过这里还有一点需要注意。让我们看下面这棵树。

                                                              

尽管每个节点都比左子节点大,比右子节点小,但这并不是一棵二叉搜索树。其中8的位置不对,比根节点6要大。

更准确地说,成为二叉搜索树的条件是:所有左边的节点必须小于当前节点,而当前节点必须小于所有右边节点。

利用这一点,我们可以通过自上而下传递最小和最大值来解决这个问题。在迭代遍历整个树的过程中,我们会用逐渐变窄的范围来检查各个节点。

实现

#include <cstdio>
#include "BinaryTree.h"
#include <iostream>

using namespace std;

bool IsSearchTree(const BinaryTreeNode* pRoot, int min, int max)
{
	if (pRoot == nullptr)
		return true;

	if (pRoot->m_nValue < min || pRoot->m_nValue >= max)
		return false;

        // 进入左子树时,更新max;进入右子树时,更新min
        // 如果任一节点不能通过检查,则停止并返回false
	if (!IsSearchTree(pRoot->m_pLeft, min, pRoot->m_nValue) || !IsSearchTree(pRoot
		->m_pRight, pRoot->m_nValue, max))
		return false;

	return true;
}

// 测试代码

// 二叉查找树
//             6
//         /      \
//        3        9
//       /\       / \
//      2  8     7   10
bool Test()
{
	BinaryTreeNode* pNode1 = CreateBinaryTreeNode(6);
	BinaryTreeNode* pNode2 = CreateBinaryTreeNode(3);
	BinaryTreeNode* pNode3 = CreateBinaryTreeNode(9);
	BinaryTreeNode* pNode4 = CreateBinaryTreeNode(2);
	BinaryTreeNode* pNode5 = CreateBinaryTreeNode(4);
	BinaryTreeNode* pNode6 = CreateBinaryTreeNode(7);
	BinaryTreeNode* pNode7 = CreateBinaryTreeNode(10);

	ConnectTreeNodes(pNode1, pNode2, pNode3);
	ConnectTreeNodes(pNode2, pNode4, pNode5);
	ConnectTreeNodes(pNode3, pNode6, pNode7);

	// Integer_min = 0x80000000
	// Integer_max = 0x7fffffff
	bool flag = IsSearchTree(pNode1, 0x80000000, 0x7fffffff);

	return flag;
}

int main()
{
	bool flag = Test();

	cout << flag << endl;

	return 0;
}复制代码

该解法的时间复杂度是(), 其中为整棵树的节点数。我们可以证明这已经是最佳做法,因为任何算法都必须访问全部N 个结点。

因为用了递归,对于平衡树,空间复杂度是O (logN )。在调用栈上,共有O (logN )个递归调用,因为递归的深度最大会到这棵树的深度。

记住,在递归算法中,一定要确定终止条件以及节点为空的情况得到妥善处理。


参考文献

[1] C++中整数最值的表示方法

[2] 《程序员面试金典》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值