主题:[讨论]怎么判断一棵二叉树是一棵二叉排序树???求高手指导!!
findlyhl
[专家分:280] 发布于 2006-04-26 12:15:00
用递归或非递归算法来判断一个二叉树是否为二叉排序树?
我知道若用中序遍历得到一个升序序列的话就是二叉排序树,但是,还存在二叉排序树的根结点可以大于等于右子树的情况~~~~~那该怎么办呢[em18] 还有就是输入一个二叉树的时候怎么处理输入的数字呢?若用字符表示的话只能是小于10的单个字符,但是也可能是11,12之类的数字,若声明为int型的,那么输入时该怎么处理?
求各位大哥大姐帮帮小妹~~~~~~~~我实在是不懂~~~~~~~~~
先谢谢了[em10]
回复列表 (共12个回复)
沙发
rickone [专家分:15390] 发布于 2006-04-26 14:34:00
bool IsSortBTree(BTree &root)
{
if(root==NULL)
return TRUE;
if(root->lchild==NULL && root->rchild==NULL)
return TRUE;
if((root->lchild!=NULL && root->lchild->data>root->data) ||
(root->rchild!=NULL && root->data>root->rchild->data))
return FALSE;
return IsSortBTree(root->lchild) && IsSortBTree(root->rchild);
}
板凳
findlyhl [专家分:280] 发布于 2006-04-26 14:55:00
谢了~~~~~~~~大哥
有没有非递归的算法啊?还有就是我之前说的那个输入问题怎么解决啊?
麻烦再帮帮忙[em2]
3 楼
findlyhl [专家分:280] 发布于 2006-04-26 16:25:00
这个是我写的,但是还是有点错误,就是输入时的错误,各位帮我改改,谢谢
#include <stdio.h>
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define M 50
typedef struct node
{
int data;
struct node *lchild,*rchild;
}btnode,*btree;
//创建一个二叉树(前序输入)
void buildbt(btree &T)
{
char ch;
int hl;
scanf("%d",&hl);
//输入数字和空格/‘#’,空格用来区分每个结点的数据信息
ch = getchar();
if(ch == '#')
T = NULL;
else
{
T = (btree)malloc(sizeof(btnode));
T->data = hl;
buildbt(T->lchild);
buildbt(T->rchild);
}
}
//判断一棵二叉树是否是一棵二叉排序树
bool pdbt(btree T)
{
if(T == NULL)
return TRUE;
if(T->lchild == NULL && T->rchild == NULL)
return TRUE;
if((T->lchild && T->lchild->data >= T->data) ||
(T->rchild && T->data > T->rchild->data))
return FALSE;
return pdbt(T->lchild);
return pdbt(T->rchild);
}
void main()
{
btree T;
printf("\n输入一个二叉树:\n");
buildbt(T);
printf("\n判断一棵二叉树是否是一棵二叉排序树:\n");
if(pdbt(T))
printf("\nyes!!!\n");
else
printf("\nno!!!\n");
}
4 楼
海上飞洪 [专家分:520] 发布于 2006-04-27 11:21:00
Status IsBSTreet(BiTree t,BiTree &pre)
{
int flag=1;
if(t->lchild && flag)
IsBSTreet(t->lchild,pre);
if(t->data.key<pre->data.key)
flag=0;
pre=t;
if(t->rchild && flag)
IsBSTreet(t->rchild,pre);
return flag;
}
这种写法对吗?
5 楼
rickone [专家分:15390] 发布于 2006-04-27 13:18:00
我那个函数完全是按二叉排序数的定义设计的:
1、如果是空树,返回真
2、否则,如果左右子树皆空,返回真
3、否则:
若左子树非空,且左结点的值>根的值(大于就是不小于或等于) 或者
若右子树非空,且根的值>右结点的值
返回假
4、否则,当且仅当左右子树都是二叉排序树时返回真,否则返回假
3楼程序最后怎可以随便改成两行return,这样第二个return是不会被执行的,没有任何逻辑覆盖,此外那个大于等于号也是改得不好啊。
4楼的程序不太明白,可以加点注释吗?
6 楼
findlyhl [专家分:280] 发布于 2006-04-28 01:06:00
若左子树非空,且左结点的值>根的值(大于就是不小于或等于) 或者
若右子树非空,且根的值>右结点的值
返回假
这个是不是不对啊?二叉排序树的定义是左子树的所有结点的值小于跟结点的值,而右子树的所有结点的值大于或等于跟结点的值。。
所以是不是应该为:
若左子树非空,且左结点的值>=根的值 或者
若右子树非空,且根的值>右结点的值
返回假
7 楼
rickone [专家分:15390] 发布于 2006-04-28 09:36:00
我疏忽了。。。
8 楼
findlyhl [专家分:280] 发布于 2006-04-28 12:31:00
6
/ \
3 8
\ /
5 6
/ \
3 8
\
5
例如这样的一棵二叉树,就不是二叉排序树
但是用你算法却验证它是一个二叉排序树
为什么呢?
bool pdbt(btree T)
{
if(T == NULL)
return TRUE;
if(T->lchild == NULL && T->rchild == NULL)
return TRUE;
if((T->lchild && T->lchild->data >= T->data) ||
(T->rchild && T->data > T->rchild->data))
return FALSE;
return pdbt(T->lchild) && pdbt(T->rchild);
}
9 楼
rickone [专家分:15390] 发布于 2006-04-28 13:35:00
1.二叉排序树的概念:
二叉排序树是一种动态树表。
二叉排序树的定义:二叉排序树或者是一棵空树,
或者是一棵具有如下性质的二叉树:
⑴ 若它的左子树非空,则左子树上所有结点的值[b]均[/b]小于根结点的值;
⑵ 若它的右子树非空,则右子树上所有结点的值[b]均[/b]大于根结点的值;
⑶ 左、右子树本身又各是一棵二叉排序树。二叉排序树的性质: 按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。
不好意思,幸好你够聪明,提醒了我,也没有误导你(:))~~
我上面的言论画把叉先。
新的思路:
判断的时候为了节省时间,不进行子树遍历,而且是‘定界’,往左走定上界,往右走定下界,如果有结点不了界之内则否定,算法这样描述:
typedef int DataType;
typedef int *LPDataType;
typedef struct _BNode{
DataType data;
struct _BNode *lchild,*rchild;
}BNode,*BTree;
bool IsBSTree(
BTree root,//判断的二叉树的根
LPDataType lpDown,//下界指针,初始为NULL
LPDataType lpUp//上界指针
)
{
if(root==NULL)
return TRUE;
if(lpDown && *lpDown >= root->data)
return FALSE;
if(lpUp && root->data > *lpUp)
return FALSE;
return IsBSTree(root->lchild,lpDown,&(root->data)) && IsBSTree(root->rchild,&(root->data),lpUp);
}
希望这次没有误导你。
10 楼
dragonbin [专家分:0] 发布于 2006-04-29 08:48:00
或者是一棵具有如下性质的二叉树:
⑴ 若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
⑵ 若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
⑶ 左、右子树本身又各是一棵二叉排序树。二叉排序树的性质: 按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。
这个、几个性质怎么没有见过啊
我来回复