今天运动会开幕式结束!国旗班顺利收关!这一阵学习落下很多,以后得花很多时间在学习上了。但也很开心圆满完成国旗班任务。
今天的题目并不很难,主要想把二叉排序树实现下,也方便我以后复习使用。
二叉排序树的实现+判别(C语言)
二叉排序树
定义
二叉排序树(BST),也叫二叉查找树。二叉排序树或者是一颗空树,
或者是一颗具有下列特性的非空二叉树:
1.若左子树非空,则左子树上所有结点关键字值均小于根结点的关键字值
2.若右子树非空,则右子树上所有结点关键字值均大于根结点的关键字值
3.左、右子树本身也分别是一颗二叉排序树。
对二叉排序树进行中序遍历,可以得到一个递增的有序序列。
例:
操作
定义
typedef struct BinTreeNode
{
int data;
struct BinTreeNode *Lchild;
struct BinTreeNode *Rchild;
}BinTreeNode,*BinTree;
建立
注意此处要用两个函数(输入-1结束)
void InsertBinTree(BinTreeNode **T,int elem)//插入二叉排序树结点(因为要从上往下一步一步找,所以一次只能插一个,不能递归)
{
if(*T==NULL)
{
*T=(BinTreeNode*)malloc(sizeof(BinTreeNode));
(*T)->data=elem;
(*T)->Lchild=NULL;
(*T)->Rchild=NULL;
}
else if(elem<(*T)->data)
InsertBinTree(&((*T)->Lchild),elem);
else if(elem>(*T)->data)
InsertBinTree(&((*T)->Rchild),elem);
}
void CreateBinTree(BinTreeNode **T)
{
int elem;
(*T)=NULL;
scanf("%d",&elem);
while(elem!=-1)
{
InsertBinTree(T,elem);
scanf("%d",&elem);
}
}
查找
查找单个元素
BinTreeNode* SelectTree(BinTreeNode *T,int elem)//查找二叉排序树中的元素
{
if(T==NULL) return NULL;
else if(T->data==elem) return T;
else if(T->data>elem) return (SelectTree(T->Lchild,elem));
else return (SelectTree(T->Rchild,elem));
查找范围内元素
void SelectRangeelem(BinTreeNode *T,int a,int b)
{
if(T)
{
SelectRangeelem(T->Lchild,a,b);
if(T->data>a&&T->data<b) printf("%d ",T->data);
SelectRangeelem(T->Rchild,a,b);
}
}
删除
void DelBST(BinTreeNode *T,int key)//在二叉排序树中删除结点
{//因为一个结点一旦有左子树,就要有区分左右大小的任务,所以以有无左子树来分类讨论
BinTreeNode *p,*f,*s,*q;
p=T;
f=NULL;
while(p)//查找为key的待删除结点
{
if(p->data==key) break;//找到则break
f=p;//f指向p的双亲结点
if(p->data>key) p=p->Lchild;
else p=p->Rchild;
}
if(p==NULL) return ;//找不到则退出
if(p->Lchild==NULL)//若p无左子树
{
if(f==NULL) free(p);//p为原树的根
else if(f->Lchild==p)//p为f的左子树
f->Lchild=p->Rchild;//把p的右子树链到f的左子树上
else//p为f的右子树
f->Rchild=p->Rchild;//把p的右子树链到f的右子树上
free(p);
}
else//p有左子树
{
q=p;
s=q->Lchild;
while(s->Rchild)
{
q=s;
s=s->Rchild;//在p的左子树中查找最右下结点(此节点为首个比待删除结点小的结点,它能肩负起区分大小的任务)
}
if(q==p) q->Lchild=s->Lchild;
else q->Rchild=s->Lchild;//把s的左子树链到s的双亲结点p的右子树(绕开s)
p->data=s->data;
free(s);
}
}
判断是否为二叉排序树
int SelectBinSortTree(BinTreeNode *T)//判断是否为二叉排序树
{
if(T==0) return 1;
else if(T->Lchild&&T->Rchild)
{
if(T->data<T->Lchild->data||T->data>T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Lchild)&&SelectBinSortTree(T->Rchild));
}
else if(T->Lchild)
{
if(T->data<T->Lchild->data) return 0;
else return(SelectBinSortTree(T->Lchild));
}
else if(T->Rchild)
{
if(T->data<T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Rchild));
}
return 1;
}
总体测试代码如下
#include<stdio.h>
#include<stdlib.h>
typedef struct BinTreeNode
{
int data;
struct BinTreeNode *Lchild;
struct BinTreeNode *Rchild;
}BinTreeNode,*BinTree;
void CreateTree(BinTreeNode **T)//建立二叉树
{
int elem;
scanf("%d",&elem);
if(elem==-1) *T=NULL;
else{
*T=(BinTreeNode*)malloc(sizeof(BinTreeNode));
(*T)->data=elem;
CreateTree(&((*T)->Lchild));
CreateTree(&((*T)->Rchild));
}
}
void InsertBinTree(BinTreeNode **T,int elem)//插入二叉排序树结点(因为要从上往下一步一步找,所以一次只能插一个,不能递归)
{
if(*T==NULL)
{
*T=(BinTreeNode*)malloc(sizeof(BinTreeNode));
(*T)->data=elem;
(*T)->Lchild=NULL;
(*T)->Rchild=NULL;
}
else if(elem<(*T)->data)
InsertBinTree(&((*T)->Lchild),elem);
else if(elem>(*T)->data)
InsertBinTree(&((*T)->Rchild),elem);
}
void CreateBinTree(BinTreeNode **T)//建立树
{
int elem;
(*T)=NULL;
scanf("%d",&elem);
while(elem!=-1)
{
InsertBinTree(T,elem);
scanf("%d",&elem);
}
}
BinTreeNode* SelectTree(BinTreeNode *T,int elem)//查找二叉排序树中的元素
{
if(T==NULL) return NULL;
else if(T->data==elem) return T;
else if(T->data>elem) return (SelectTree(T->Lchild,elem));
else return (SelectTree(T->Rchild,elem));
}
void SelectRangeelem(BinTreeNode *T,int a,int b)//查找范围内元素
{
if(T)
{
SelectRangeelem(T->Lchild,a,b);
if(T->data>a&&T->data<b) printf("%d ",T->data);
SelectRangeelem(T->Rchild,a,b);
}
}
int SelectBinSortTree(BinTreeNode *T)//判断是否为二叉排序树
{
if(T==0) return 1;
else if(T->Lchild&&T->Rchild)
{
if(T->data<T->Lchild->data||T->data>T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Lchild)&&SelectBinSortTree(T->Rchild));
}
else if(T->Lchild)
{
if(T->data<T->Lchild->data) return 0;
else return(SelectBinSortTree(T->Lchild));
}
else if(T->Rchild)
{
if(T->data<T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Rchild));
}
return 1;
}
void printOrder(BinTreeNode *T)//输出树
{
if(T==NULL)return;
printOrder(T->Lchild);
printf("%d ",T->data);
printOrder(T->Rchild);
}
void DelBST(BinTreeNode *T,int key)//在二叉排序树中删除结点
{//因为一个结点一旦有左子树,就要有区分左右大小的任务,所以以有无左子树来分类讨论
BinTreeNode *p,*f,*s,*q;
p=T;
f=NULL;
while(p)//查找为key的待删除结点
{
if(p->data==key) break;//找到则break
f=p;//f指向p的双亲结点
if(p->data>key) p=p->Lchild;
else p=p->Rchild;
}
if(p==NULL) return ;//找不到则退出
if(p->Lchild==NULL)//若p无左子树
{
if(f==NULL) free(p);//p为原树的根
else if(f->Lchild==p)//p为f的左子树
f->Lchild=p->Rchild;//把p的右子树链到f的左子树上
else//p为f的右子树
f->Rchild=p->Rchild;//把p的右子树链到f的右子树上
free(p);
}
else//p有左子树
{
q=p;
s=q->Lchild;
while(s->Rchild)
{
q=s;
s=s->Rchild;//在p的左子树中查找最右下结点(此节点为首个比待删除结点小的结点,它能肩负起区分大小的任务)
}
if(q==p) q->Lchild=s->Lchild;
else q->Rchild=s->Lchild;//把s的左子树链到s的双亲结点p的右子树(绕开s)
p->data=s->data;
free(s);
}
}
int main()
{
BinTreeNode *T;
CreateTree(&T);
//CreateBinTree(&T);
printOrder(T);
DelBST(T,12);
printOrder(T);
//BinTreeNode *Tfind;
//Tfind=SelectTree(T,48);
//printf(" %d",Tfind->data);
//if(SelectBinSortTree(T))
//{
// printf("yes");
//}
// else printf("no");
return 0;
}
(读者根据需求自行测试便可)
题目(二叉排序树的判别)
#include<stdio.h>
#include<stdlib.h>
typedef struct BinTreeNode
{
int data;
struct BinTreeNode *Lchild;
struct BinTreeNode *Rchild;
}BinTreeNode,*BinTree;
void CreateBinTree(BinTreeNode **T)//建立二叉树
{
int elem;
scanf("%d",&elem);
if(elem==-1) *T=NULL;
else{
*T=(BinTreeNode*)malloc(sizeof(BinTreeNode));
(*T)->data=elem;
CreateBinTree(&((*T)->Lchild));
CreateBinTree(&((*T)->Rchild));
}
}
int SelectBinSortTree(BinTreeNode *T)//判断
{
if(T==0) return 1;
else if(T->Lchild&&T->Rchild)
{
if(T->data<T->Lchild->data||T->data>T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Lchild)&&SelectBinSortTree(T->Rchild));
}
else if(T->Lchild)
{
if(T->data<T->Lchild->data) return 0;
else return(SelectBinSortTree(T->Lchild));
}
else if(T->Rchild)
{
if(T->data<T->Rchild->data) return 0;
else return(SelectBinSortTree(T->Rchild));
}
return 1;
}
void printOrder(BinTreeNode *T)
{
if(T==NULL)return;
printOrder(T->Lchild);
printf("%d ",T->data);
printOrder(T->Rchild);
}
int main()
{
BinTreeNode *T;
CreateBinTree(&T);
//printOrder(T);
if(SelectBinSortTree(T))
{
printf("yes");
}
else printf("no");
return 0;
}
我们中序输出:
可见为递增有序数列。