680 字
2 分钟
判断是否为二叉搜索树
判断是否为二叉搜索树
一、引言
众所周知啊,我们的二叉搜索树的定义是:左子树所有节点都小于根节点,右子树所有节点都大于根节点。
二叉搜索树既然满足上面的特性,那么对于他的子树来说,也是一个二叉搜索树,如下图,是一个递归结构。

那么我们利用这个定义就能来判断是否为二叉搜索树。
二、初次尝试
一种比较直观的思路就是通过递归遍历左子树,来判断是否每个节点都小于根。右子树同理。
我们来用cpp实现一下。
bool issubtreeless(Node* root,int value){ //判断子节点是否小于根节点 if(root==NULL)return true; if(root->data<=value &&issubtreeless(root->left,value) &&issubtreeless(root->right,value) ){ return true; } else return false;}bool issubtreegreater(Node* root,int value){ //判断子节点是否大于根节点 if(root==NULL)return true; if(root->data>value &&issubtreeless(root->left,value) &&issubtreeless(root->right,value) ){ return true; } else return false;}这里是比较了左右子树每一个节点与根节点大小的两个函数,同样,你也可以写一个找到左右最大最小值的函数,效果和开销是一样的!
bool isbinarysearchtree(Node *root){ if(root==NULL)return true; if(issubtreeless(root->left,root->data) &&issubtreegreater(root->right,root->data) &&isbinarysearchtree(root->left) &&isbinarysearchtree(root->right) ) return true; else return false;}这是判断是否为二叉搜索树的函数,判断原则是:左子树小于等于根,右子树大于根,左右子树均为二叉搜索树!
这里几乎用了四次递归!甚至不包含比较函数里面的递归,开销大的一批!但凡树的高度要大一点,那么我们的栈随时都可能溢出~!
很显然,这个方案不理想。
三、头铁
既然解决不了,那就换方法🤔
众所周知啊,我们的二叉搜索树的定义是:左子树所有节点都小于根节点,右子树所有节点都大于根节点。
回想一下这句话,我们依然要拟合出这种效果,那么有没有更好的方法。
有的,兄弟有的。
我们可以对每个节点设置范围限制。
什么意思?就是约束一个节点,让其处于自己该处于的位置。看看我精心画的图,你绝对猜不到我的无穷符号是怎么弄出来的😎

根节点任意范围,其他节点则收到约束(左孩子比他小,右孩子比他大)
现在我们来实现一下吧!
bool isbinarysearchtree(Node *root,int minvalue, int maxvalue){ if(root==NULL)return true; if(root->data>=minvalue &&root->data<maxvalue &&isbinarysearchtree(root->left,minvalue,root->data) &&isbinarysearchtree(root->right,root->data,maxvalue) ) return true; else return false;}如何实现的?我们通过判断当前节点的值是否在限制范围内进行一个递归,同时会检查所有的子树是否符合限制。
如果你不习惯一个函数有三个参数,可以把传入root给剥离出来,剩下的作为工具函数即可!
部分信息可能已经过时









