判断一棵树是否是二叉搜索树

前两天写过一篇博文《二叉搜索树基本操作实现》,为了更深入了解二叉搜索树的性质,本文实现判断一棵树是否为二叉搜索树算法。

二叉搜索树的性质:

任意节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。

构造二叉树的节点定义为:

struct TreeNode{
    int data;
    TreeNode *left;
    TreeNode *right;
};

方法1 (错误)

对每一个节点,检测其值是否大于左子树节点,是否小于右子树节点。思路很简单,代码实现如下:

bool isBST(TreeNode* root)
{
    if (root == NULL)
        return true;
    if (root->left != NULL && root->left->data> root->data)
        return false;
    if (root->right != NULL && root->right->data < root->data)
        return false;
    if (!isBST(root->left) || !isBST(root->right))
        return false;
    return true;
}

但是,这种方法是错误的,如下面例子,节点4大于根节点3,但上面函数检测这棵树是BST。

3

/      \

2         5

/     \

1         4

方法2 

对每个节点,检测其值是否大于左子树的最大值,是否小于右子树的最小值。思路正确,但效率较低,代码实现如下:

int maxValue(TreeNode *root)
{
    int max = root->data;
    if(root->left != NULL)
    {
        int maxLeft = maxValue(root->left);
        max = max > maxLeft ? max : maxLeft;
    }
    if(root->right != NULL)
    {
        int maxRight = maxValue(root->right);
        max = max > maxRight ? max : maxRight;
    }
    return max;
}

int minValue(TreeNode *root)
{
    int min = root->data;
    if(root->left != NULL)
    {
        int minLeft = maxValue(root->left);
        min = min > minLeft ? min : minLeft;
    }
    if(root->right != NULL)
    {
        int minRight = maxValue(root->right);
        min = min > minRight ? min : min;
    }
    return min;
}

bool isBST(TreeNode *root)
{
    if(root == NULL)
        return true;
    if(root->left != NULL && maxValue(root->left) > root->data)
        return false;
    if(root->right != NULL && minValue(root->right) < root->data)
        return false;
    return isBST(root->left) && isBST(root->right);
}

其中,maxValue及minValue函数,分别返回一棵非空二叉树的最大值和最小值。

方法3

方法2需要重复遍历树中的部分数据,故效率较低,如果只需每个节点遍历一次,那么效率将大大提高。方法3的巧妙之处在于限定了子树节点的值得范围,从而每个节点只需遍历一次。节点值的初始范围可限定为TNT_MIN以及TNT_MAX。代码实现如下:

bool isBSTUtil(TreeNode *root, int min, int max)
{
    if(root == NULL)
        return true;
    if(root->data < min || root->data > max)
        return false;
    return isBSTUtil(root->left, min, root->data - 1) && isBSTUtil(root->right, root->data + 1, max);
}

bool isBST(TreeNode *root)
{
    return isBST02(root, INT_MIN, INT_MAX);
}

方法4

使用中序遍历的方法实现:

1)对树进行中序遍历,将结果保存在temp数组中;

2)检测temp数组是否为升序排列,如果是,则为BST,反之则不是。

此方法还可以进一步的优化,不用temp数组,避免使用额外的内存开销。在中序遍历时使用静态变量保存前驱节点,如果当前节点小于前驱节点,则该树不是BST。代码实现如下:

//中序遍历的方法实现
bool isBST(TreeNode *root)
{
    static TreeNode *prev;
    if(root != NULL)
    {
        if(!isBST(root->left))
            return false;
        if(prev != NULL && root->data < prev->data)
            return false;
        prev = root;
        if(!isBST(root->right))
            return false;
    }
    return true;
}

二叉搜索树的判断是一个重要的算法,个人认为该算法的实现在考研或找工作中都非常重要,从这个算法可以考核到对二叉树特别是二叉搜索树的特性的了解。所以掌握好这个算法的思想和实现时非常必要的。

本文参考于https://www.2cto.com/kf/201506/408372.html,只是在其基础上加上自己的一些见解,谢谢原作者。

原文地址:https://www.cnblogs.com/evenleee/p/8474496.html

时间: 2024-08-03 06:40:43

判断一棵树是否是二叉搜索树的相关文章

判断一棵树是否为二叉搜索树(二叉排序树) python

输入一棵树,判断这棵树是否为二叉搜索树.首先要知道什么是排序二叉树,二叉排序树是这样定义的,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值: (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值: (3)左.右子树也分别为二叉排序树: (4)没有键值相等的节点 #方法1,直接判断 直接判断的关键在于不能只是单纯地判断根.左.右三个节点的大小关系,左子树的右节点不仅要大于父节点,还要小于父节点的父节点,右子树的左节点

判断一棵树是否是二叉平衡树

主要就是判断二叉树深度进行改造.判断条件为左树为平衡树,右树为平衡树,并且左树的高度和右树的高度插不超过-1:public class IsAVL { public static class Node{ private Node left; private Node right; private int value; public Node(int value){ this.value = value; } } public static int isAVL(Node head){ if(hea

数据结构学习笔记04树(二叉树、二叉搜索树、平衡二叉树)

一.树 树的基本术语 ①结点的度(Degree):结点的子树个数 ②树的度:树的所有结点中最大的度数 ③叶结点(Leaf):度为0的结点 ④父结点(Parent):有子树的结点是其子树的根结点的父结点 ⑤子结点(Child):若A结点是B结点的父结点,则称B结点是A结点的子结点:子结点也称孩子结点. ⑥兄弟结点(Sibling):具有同一父结点的各结点彼此是兄弟结点. ⑦路径和路径长度:从结点n1到nk的路径为一个结点序列n1 , n2 ,… , nk , ni是 ni+1的父结点.路径所包含边

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树 的搜索性能逼近二分查找:但它比连续内存空间的二分查找的优点是,改变BST树结构 插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销: 如:

判断某数组是否是某二叉搜索树的后序遍历的结果

题目: 输入一个数组,判断该数组是不是某二叉搜索树的后序遍历结果. 解答: 1 public class Solution { 2 3 public static void main(String[] args) { 4 int[] array = {5,7,6,9,11,10,8}; 5 6 boolean b = verfiySequenceOfBST(array, 0, 6); 7 System.out.println(b); 8 } 9 10 private static boolean

【剑指offer】【树】54.二叉搜索树的第k大节点

二叉搜索树的第k大节点 递归法 中序遍历的二叉搜索树序列为单调递增的序列,将中序遍历的结果放到vector中,第k大的数为v.size()-k位置的数 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ cl

【LeetCode-面试算法经典-Java实现】【098-Validate Binary Search Tree(验证二叉搜索树)】

[098-Validate Binary Search Tree(验证二叉搜索树)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys le

判断一颗二叉树是否为二叉平衡树 python 代码

输入一颗二叉树,判断这棵树是否为二叉平衡树.首先来看一下二叉平衡树的概念:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.因此判断一颗二叉平衡树的关键在于求出左右子树的高度差,而二叉树的高度又是怎么定义的呢?二叉树的高度指的是从根节点到叶子节点所有路径上包含节点个数的最大值.所以我们可以得出,父亲节点的高度与左右子树高度的关系为:父亲节点的高度=max(左子树高度,右子树高度)+1,同时我们知道,叶子节点的高度值为1(或则0,这里定义1或者0对判断结

PTA 7-28 搜索树判断(镜像二叉搜索树的后序遍历)

算法源代码在 Veeupup Github 考点: 二叉搜索树遍历方式和性质运用 对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值.如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树. 现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列. 输入格式: 输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,