回 帖 发 新 帖 刷新版面

主题:[讨论]怎么判断一棵二叉树是一棵二叉排序树???求高手指导!!

用递归或非递归算法来判断一个二叉树是否为二叉排序树?
我知道若用中序遍历得到一个升序序列的话就是二叉排序树,但是,还存在二叉排序树的根结点可以大于等于右子树的情况~~~~~那该怎么办呢[em18]  还有就是输入一个二叉树的时候怎么处理输入的数字呢?若用字符表示的话只能是小于10的单个字符,但是也可能是11,12之类的数字,若声明为int型的,那么输入时该怎么处理?
求各位大哥大姐帮帮小妹~~~~~~~~我实在是不懂~~~~~~~~~
先谢谢了[em10]

回复列表 (共12个回复)

沙发

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);
}

板凳

谢了~~~~~~~~大哥
有没有非递归的算法啊?还有就是我之前说的那个输入问题怎么解决啊?
麻烦再帮帮忙[em2]

3 楼

这个是我写的,但是还是有点错误,就是输入时的错误,各位帮我改改,谢谢
#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 楼

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 楼

我那个函数完全是按二叉排序数的定义设计的:
1、如果是空树,返回真
2、否则,如果左右子树皆空,返回真
3、否则:
 若左子树非空,且左结点的值>根的值(大于就是不小于或等于) 或者
 若右子树非空,且根的值>右结点的值
 返回假
4、否则,当且仅当左右子树都是二叉排序树时返回真,否则返回假

3楼程序最后怎可以随便改成两行return,这样第二个return是不会被执行的,没有任何逻辑覆盖,此外那个大于等于号也是改得不好啊。

4楼的程序不太明白,可以加点注释吗?

6 楼


若左子树非空,且左结点的值>根的值(大于就是不小于或等于) 或者
 若右子树非空,且根的值>右结点的值
 返回假

这个是不是不对啊?二叉排序树的定义是左子树的所有结点的值小于跟结点的值,而右子树的所有结点的值大于或等于跟结点的值。。

所以是不是应该为:
若左子树非空,且左结点的值>=根的值 或者
 若右子树非空,且根的值>右结点的值
 返回假

7 楼

我疏忽了。。。

8 楼


          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 楼

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 楼

或者是一棵具有如下性质的二叉树:
     ⑴ 若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
     ⑵ 若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
     ⑶ 左、右子树本身又各是一棵二叉排序树。二叉排序树的性质: 按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。


这个、几个性质怎么没有见过啊

我来回复

您尚未登录,请登录后再回复。点此登录或注册