问题

给定一棵二叉树,判定该二叉树是否是二叉搜索树(Binary Search Tree)?

解法1:暴力搜索

首先说明一下二叉树和二叉搜索树的区别。二叉树指这样的树结构,它的每个结点的孩子数目最多为2个;二叉搜索树是一种二叉树,但是它有附加的一些约束条件,这些约束条件必须对每个结点都成立:
  • 结点node的左子树所有结点的值都小于node的值。
  • 结点node的右子树所有结点的值都大于node的值。
  • 结点node的左右子树同样都必须是二叉搜索树。
该问题在面试中也许经常问到,考察的是对二叉搜索树定义的理解。初看这个问题,也许会想这样来实现:
假定当前结点值为k。对于二叉树中每个结点,判断其左孩子的值是否小于k,其右孩子的值是否大于k。如果所有结点都满足该条件,则该二叉树是一棵二叉搜索树。
很不幸的是,这个算法是错误的。考虑下面的二叉树,它符合上面算法的条件,但是它不是一棵二叉搜索树。
    10/  \5   15     -------- binary tree (1)/  \6    20

那么,根据二叉搜索树的定义,可以想到一种暴力搜索的方法来判定二叉树是否为二叉搜索树。

 假定当前结点值为k。则对于二叉树中每个结点,其左子树所有结点的值必须都小于k,其右子树所有结点的值都必须大于k。

暴力搜索算法代码如下,虽然效率不高,但是它确实能够完成工作。该解法最坏情况复杂度为O(n^2),n为结点数目。(当所有结点都在一边的时候出现最坏情况)

/*判断左子树的结点值是否都小于val*/
bool isSubTreeLessThan(BinaryTree *p, int val)
{if (!p) return true;return (p->data < val &&isSubTreeLessThan(p->left, val) &&isSubTreeLessThan(p->right, val));
}/*判断右子树的结点值是否都大于val*/
bool isSubTreeGreaterThan(BinaryTree *p, int val)
{if (!p) return true;return (p->data > val &&isSubTreeGreaterThan(p->left, val) &&isSubTreeGreaterThan(p->right, val));
}/*判定二叉树是否是二叉搜索树*/
bool isBSTBruteForce(BinaryTree *p)
{if (!p) return true;return isSubTreeLessThan(p->left, p->data) &&isSubTreeGreaterThan(p->right, p->data) &&isBSTBruteForce(p->left) &&isBSTBruteForce(p->right);
}

一个类似的解法是:对于结点node,判断其左子树最大值是否大于node的值,如果是,则该二叉树不是二叉搜索树。如果不是,则接着判断右子树最小值是否小于或等于node的值,如果是,则不是二叉搜索树。如果不是则接着递归判断左右子树是否是二叉搜索树。(代码中的maxValue和minValue函数功能分别是返回二叉树中的最大值和最小值,这里假定二叉树为二叉搜索树,实际返回的不一定是最大值和最小值)

int isBST(struct node* node)
{ if (node==NULL) return(true);//如果左子树最大值>=当前node的值,则返回falseif (node->left!=NULL && maxValue(node->left) >= node->data) return(false);// 如果右子树最小值<=当前node的值,返回falseif (node->right!=NULL && minValue(node->right) <= node->data) return(false);// 如果左子树或者右子树不是BST,返回falseif (!isBST(node->left) || !isBST(node->right)) return(false);// 通过所有测试,返回truereturn(true);
} 

解法2:更好的解法

以前面提到的binary tree(1)为例,当我们从结点10遍历到右结点15时,我们知道右子树结点值肯定都在 10和+INFINITY(无穷大)之间 当我们遍历到结点15的左孩子结点6时,我们知道结点15的左子树结点值都必须在10到15之间。显然,结点6不符合条件,因此它不是一棵二叉搜索树。该算法代码如下:
int isBST2(struct node* node)
{return(isBSTUtil(node, INT_MIN, INT_MAX));
}
/*
给定的二叉树是BST则返回true,且它的值  >min 以及 < max.
*/
int isBSTUtil(struct node* node, int min, int max)
{if (node==NULL) return(true);// 如果不满足min和max约束,返回falseif (node->data<=min || node->data>=max) return(false);// 递归判断左右子树是否满足min和max约束条件returnisBSTUtil(node->left, min, node->data) &&isBSTUtil(node->right, node->data, max));
}

由于该算法只需要访问每个结点1次,因此时间复杂度为O(n),比解法1效率高很多。

解法3:中序遍历算法

因为一棵二叉搜索树的中序遍历后其结点值是从小到大排好序的,所以依此给出下面的解法。该解法时间复杂度也是O(n)。
bool isBSTInOrder(BinaryTree *root)
{int prev = INT_MIN;return isBSTInOrderHelper(root, prev);
}
/*该函数判断二叉树p是否是一棵二叉搜索树,且其结点值都大于prev*/
bool isBSTInOrderHelper(BinaryTree *p, int& prev)
{if (!p) return true;if (isBSTInOrderHelper(p->left, prev)) { // 如果左子树是二叉搜索树,且结点值都大于previf (p->data > prev) { //判断当前结点值是否大于prev,因为此时prev已经设置为已经中序遍历过的结点的最大值。prev = p->data;return isBSTInOrderHelper(p->right, prev); //若结点值大于prev,则设置prev为当前结点值,并判断右子树是否二叉搜索树且结点值都大于prev。} else {return false;}}else {return false;}
}

判定一棵二叉树是否是二叉搜索树相关推荐

  1. 数据结构---判断一棵树是否是二叉搜索树

    数据结构-判断一棵树是否是二叉搜索树 代码: #pragma once #define N 100 #define elemType BTree* #include<stdlib.h> t ...

  2. 判断二叉树是否为二叉搜索树

    1.题目 给定一棵二叉树的根节点,判断其是否为二叉搜索树. 2.分析 二叉搜索树:每一棵子树的根节点,左子树的值比根节点的值小,右子树的值比根节点的值大. 经典的二叉搜索树是没有重复值的.如果要放重复 ...

  3. C语言判断二叉树是否为二叉搜索树(附完整源码)

    C语言判断二叉树是否为二叉搜索树 C语言判断二叉树是否为二叉搜索树完整源码(定义,实现,main函数测试) C语言判断二叉树是否为二叉搜索树完整源码(定义,实现,main函数测试) #include ...

  4. 按照层次序列创建二叉树,并判断二叉树是否为二叉搜索树

    首先定义树节点的数据结构,如下: struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; 两个函数,用 ...

  5. 二叉树查找python_二叉搜索树的python实现

    介绍 二叉查找树(Binary Search Tree),也称为二叉搜索树.有序二叉树或排序二叉树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节 ...

  6. c++判断二叉树是否为二叉搜索树_原创 | 好端端的数据结构,为什么叫它SB树呢?...

    点击上方蓝字,关注并星标,和我一起学技术. 大家好,今天给大家介绍一个很厉害的数据结构,它的名字就很厉害,叫SB树,业内大佬往往叫做傻叉树.这个真不是我框你们,而是它的英文缩写就叫SBT. SBT其实 ...

  7. 4-2-6 二叉树及其遍历 / 二叉搜索树 / 完全二叉树 完全二叉搜索树 (30 分)

    一个无重复的非负整数序列,必定对应唯一的一棵形状为完全二叉树的二叉搜索树.本题就要求你输出这棵树的层序遍历序列. 输入格式: 首先第一行给出一个正整数 N(≤1000),随后第二行给出 N 个不重复的 ...

  8. C++初阶学习————二叉树进阶(二叉搜索树)

    二叉树进阶 二叉搜索树的概念 二叉搜索树的操作 基本框架 二叉搜索树的插入 二叉搜索树的查找 二叉搜索树的删除 整体代码 循环写法 递归写法 二叉搜索树的应用 二叉搜索树的性能分析 前面的文章介绍过二 ...

  9. 二叉树OJ(一)二叉树的最大深度 二叉搜索树与双向链表 对称的二叉树

    二叉树的最大深度 二叉树中和为某一值的路径(一) 二叉搜索树与双向链表 对称的二叉树 二叉树的最大深度 描述 求给定二叉树的最大深度, 深度是指树的根节点到任一叶子节点路径上节点的数量. 最大深度是所 ...

最新文章

  1. svn命令行使用说明
  2. HDU 2612 Find a way
  3. 猫咪藏在哪个房间python作业_python练习题之 猫2
  4. 【面向对象】面向对象程序设计测试题7-对象之间的has-a/many关系测试题
  5. html5 开发工具_前端HTML5开发工具有哪些呢?
  6. 各浏览器中的鼠标滚轮事件处理
  7. 【分享】伙伴们!关注公众号要慎重!这半年我取关了很多,这几个留下了!真心推荐给你!...
  8. 常用的HTML5和CSS3标签及用法(入门篇)
  9. python logger.debug_python处理logger日志
  10. 从execl表中随机抽取几行数据
  11. nodejs websocket 聊天应用
  12. Git 修改历史 commit 提交信息
  13. JAVA房屋租赁管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
  14. NLP专题直播 | Transformer, BERT, ALBERT, XLNet全面解析(ALBERT第一作者亲自讲解)
  15. #图书管理系统的设计与实现#
  16. Intellij IDEA的安装及使用介绍
  17. 法国童话故事《小王子》读后感
  18. 高位在前低位在后是啥意思_深度被套后应该如何补仓?终于有人把它讲明白了,精髓都在这里,学会了被套将与你永远无缘...
  19. 利用matlab绘制系统开环幅频渐进特性曲线(附详细注释)
  20. 今日头条的文章推荐机制是什么?

热门文章

  1. Prompt Engineering 入门(一)
  2. 【Go语言实战】13. Go语言context标准库(下)
  3. 统计学-基于R (第四版) 贾俊平编著 第二章: 数据可视化 2.1, 2.2 习题答案 【自用】
  4. 互联网早报:滴滴正式启动造车,滴滴副总裁、小桔车服总经理杨峻负责
  5. 解决以Error: GlobalConfigUtils setMetaData Fail ! 为基础的嵌套问题(包括common troller,commonservice等问题)
  6. 【经验分享】桥接网络无法联网、开发板挂载根文件系统问题解决
  7. vs2019如何关闭自动更新
  8. 铁路计算机应用期刊级别,铁路单位评审高级职称可以发表哪些期刊呢?
  9. nps+Proxifier搭建socks5代理隧道进行内网穿透
  10. 【简单3d网络游戏制作】——基于Unity