一、什么是二叉搜索树?
通俗理解,对于每一个结点,这个结点的左孩子小于中间结点,中间结点小于右孩子。
比如下面这个树
如果对这个树进行中序遍历【左->中->右】就会得到如下序列
1,2,3,4,5,6
可以发现,对于二叉搜索树,如果我们用中序遍历,最终得到的是一个递增序列。
那反之,如果对一个二叉树进行中序遍历,最终得到一个有序序列,那这个二叉树就是一个二叉搜索树。
二、判断二叉搜索树的思路
上面我们分析出来,对一个二叉搜索树用中序遍历会得到一个有序的序列。
那这个单调有序序列有什么特点呢?
对于每一个结点,这个结点都大于它的前一个结点。
那我们就可以根据上面这一条特点来整理思路。
如上图:
我们在对二叉树进行遍历的时候,定义个
pre指针
,始终指向当前结点的前一个结点,每遍历一个结点都对这个结点和上一个结点进行大小比较。
如果,当前结点大于前一个结点,说明这个顺序是符合二叉搜索树的;
如果,当前结点不大于前一个结点,说明这个顺序不符合二叉搜索树,返回false。
用上面的逻辑,将整个二叉树遍历完,就得到最终的结果了。
三、代码实现
按照上面的逻辑,我们来看代码
long long maxVal = LONG_MIN;//定义全局变量maxVal
//这个值有什么用呢,刚才说了,中序遍历的每一个结点都要和上一个结点作比较
//判断当前节点是不是大于上一个结点。所以,maxVal是用来保存当前结点的,
//因为当前结点是要大于上一个结点,所以起名为maxVal
template<class T>
bool isValidBST(Treenode<T>* node) {
//1.递归函数终止的条件
if (node == NULL) return true;//如果访问到的空节点,返回true,注意,空子树空树也是满足二叉搜索树的
//2.中序递归遍历左子树
bool left = isValidBST(node->left);
//3.中序递归遍历中间结点
//这个算法的核心,就是用当前遍历的结点和上一次遍历的结点做比较
//注意,这里的maxVal是在函数之外定义的全局变量,所以,因为递归算法,
//maxVal会被第一个遍历的结点赋值,也就是树中最小的结点赋值,
//然后,第二个遍历的结点会和maxVal作比较。一次类推
if (maxVal < node->val) maxVal = node->val;
else return false;
//4.中序递归遍历右子树
bool right = isValidBST(node->right);
return left && right;//这里对每个结点的左右子树返回的结果取交集
//也就是说,对于每一个结点,左右子树只要有一遍不符合二叉搜索树,都会返回false
//那对于整个树,只要有一个结点返回false整体就会返回false,整个树就不是二叉搜索树了
}