题目
本题要求实现函数,判断给定二叉树是否二叉搜索树。
函数接口定义:
bool IsBST ( BinTree T );
其中BinTree
结构定义如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
函数IsBST
须判断给定的T是否二叉搜索树,即满足如下定义的二叉树:
定义:一个二叉搜索树是一棵二叉树,它可以为空。如果不为空,它将满足以下性质:
非空左子树的所有键值小于其根结点的键值。
非空右子树的所有键值大于其根结点的键值。
左、右子树都是二叉搜索树。
如果T是二叉搜索树,则函数返回true
,否则返回false
。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree BuildTree(); /* 由裁判实现,细节不表 */
bool IsBST ( BinTree T );
int main()
{
BinTree T;
T = BuildTree();
if ( IsBST(T) ) printf("Yes\n");
else printf("No\n");
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例1:
如下图
输出样例1:
Yes
输入样例2:
如下图
输出样例2:
No
方法一
如果是空树或者左右子树为空,直接返回true;
如果当前根节点的左右子树有一个不是二叉搜索树,返回false(这里用递归判断);
如果根节点的数据小于左孩子的数据或者大于右孩子的数据,返回false(注意判断左右孩子非空);
接下来找到左子树的最右节点和右子树最左节点,要求左子树最右节点数值<根节点数值<右子树最左节点数值。
bool IsBST ( BinTree T ){
if(!T || (!T->Left && !T->Right)){
return true;
}else if(!IsBST(T->Left) && !IsBST(T->Right)){
// 判断左右子树是否都为二叉搜索树(递归),如果该条件不满足肯定不是;
return false;
}else if( T->Left?T->Left->Data > T->Data:0 || T->Right?T->Right->Data < T->Data:0){
return false;
}else{
// 找到左子树的最右节点和右子树最左节点。
//要求左子树最右节点数值<根节点数值<右子树最左节点数值
// 注意对左右孩子非空的判断!!!
BinTree TLeft, TRight;
if(T->Left){
TLeft=T->Left;
while(TLeft->Right){
TLeft=TLeft->Right;
}
}
if(T->Right){
TRight=T->Right;
while(TRight->Left){
TRight=TRight->Left;
}
}
return (T->Left?T->Data > TLeft->Data:1 && T->Right?T->Data < TRight->Data:1);
}
}
第一个else if与第二个else if 顺序可以对调,不影响结果
方法二
易知二叉搜索树中一个非空结点有四种情况:
1.左空&&右空;
2.左空&&右非空;
3.左非空&&右空;
4.左非空&&右非空。
递归出口:左空&&右空;
递归函数:其余情况。
二叉树结点的必要条件:大于左子树最大值,小于右子树最小值。
代码来源
bool IsBST ( BinTree T ){
BinTree p=NULL;
if(!T){ /*递归出口*/
return true;
}
else{ /*非空树*/
if(!T->Left){
if(!T->Right) /*左空&&右空:递归出口*/
return true;
else{ /*左空&&右非空:需要判断右子树*/
p = T->Right;
while(p->Left){
p = p->Left;
}
if(T->Data >= p->Data)
return false;
else
return IsBST(T->Right);
}
}
else{ /*左非空:需判断左子树*/
p = T->Left;
while(p->Right){
p = p->Right;
}
if(T->Data <= p->Data)
return false;
else{
if(!T->Right) /*左非空&&右空:无需判断右子树*/
return IsBST(T->Left);
else{ /*左非空&&右非空:需判断右子树*/
p = T->Right;
while(p->Left){
p = p->Left;
}
if(T->Data >= p->Data)
return false;
else
return ( IsBST(T->Left) && IsBST(T->Right) );
}
}
}
}
}