二叉排序树
二叉排序树的特点
- 若左子树不空,则左子树所有结点值均小于根结点
- 若右子树不空,则右子树所有结点值均大于根结点
- 二叉树排序树的中序遍历结果即为元素的升序序列
插入操作(构造排序树)
Status InsertBST(BiTree *T,TElemType e)
{
if((*T)==NULL)
{
(*T)=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild=(*T)->rchild=NULL;
(*T)->data=e;
return TRUE;
}
if(e<(*T)->data)//小于根结点时,插入到左子树
InsertBST(&(*T)->lchild, e);
else//大于根结点时,插入到右子树
InsertBST(&(*T)->rchild, e);
return FALSE;
}
通过插入构造二叉排序的过程,就相当于递归方式先序遍历二叉树的过程;
查找
指针p返回指向元素所在结点的指针,指针f始终指向*p的双亲结点
Status SearchBST(BiTree T,TElemType key,BiTree f ,BiTree *p)
{
if(!T)
{
*p=f;
printf("查找失败\n");
return FALSE;
}
else if(T->data==key)
{
*p=T;
printf("查找成功\n");
return TRUE;
}
else if(T->data>key)
return SearchBST(T->lchild, key,T, p);
else
return SearchBST(T->rchild, key,T, p);
}
删除结点
所要删除的结点有三种情况
- 该结点只有左子树
- 该结点只有右子树
- 该结点即有左子树又有右子树
//假设要删除结点10
第一种:
100
/ \
10 200
/
8
只需将结点8替换10,并释放10所在结点的存储空间即可
第二种:
100
/ \
10 200
\
20
将右子树20重接到10的位置,并释放10所在结点的存储空间
第三种:
100
/ \
10 200
/ \
4 20
/ \
3 7
/ \
6 9
/
8
根据中序遍历的性质,8所在结点为9所在结点的“前驱”,对于上图,只需,10所在结点的指针域用9替换,结点8接到7的右子树;
如图所示
100
/ \
9 200
/ \
4 20
/ \
3 7
/ \
6 8
第三种情况的另外一种形式为
100
/ \
10 200
/ \
4 20
/
3
此时直接结点10用其左子树替换即可
变为
100
/ \
4 200
/ \
3 20
Status DeleteBST(BiTree *T,TElemType key)
{
if(!T)
return FALSE;
else
{
if(key==(*T)->data)
return Delete(T);
else if(key<(*T)->data)
DeleteBST(&(*T)->lchild, key);
else
DeleteBST(&(*T)->rchild, key);
return TRUE;
}
}
Status Delete(BiTree *p)
{
BiTree q,s;
if(!(*p)->rchild)//右子树为空
{
q=(*p); (*p)=(*p)->lchild;free(q);
}
else if(!(*p)->lchild)//左子树为空
{
q=(*p);(*p)=(*p)->rchild;free(q);
}
else
{
q=(*p);s=(*p)->lchild;
while(s->rchild)
{
q=s;s=s->rchild;
}
(*p)->data=s->data;
if(q!=(*p))
q->rchild=s->rchild;
else
q->lchild=s->lchild;
free(s);
}
return TRUE;
}
完整代码:
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//查找(指针p返回结点指针)
Status SearchBST(BiTree T,TElemType key,BiTree f ,BiTree *p)
{
if(!T)
{
*p=f;
printf("查找失败\n");
return FALSE;
}
else if(T->data==key)
{
*p=T;
printf("查找成功\n");
return TRUE;
}
else if(T->data>key)
return SearchBST(T->lchild, key,T, p);
else
return SearchBST(T->rchild, key,T, p);
}
//插入(不要输入相同元素)
Status InsertBST(BiTree *T,TElemType e)
{
if((*T)==NULL)
{
(*T)=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild=(*T)->rchild=NULL;
(*T)->data=e;
return TRUE;
}
if(e<(*T)->data)
InsertBST(&(*T)->lchild, e);
else
InsertBST(&(*T)->rchild, e);
return FALSE;
}
//删除结点过程
Status Delete(BiTree *p)
{
BiTree q,s;
if(!(*p)->rchild)//右子树为空
{
q=(*p); (*p)=(*p)->lchild;free(q);
}
else if(!(*p)->lchild)//左子树为空
{
q=(*p);(*p)=(*p)->rchild;free(q);
}
else
{
q=(*p);s=(*p)->lchild;
while(s->rchild)
{
q=s;s=s->rchild;
}
(*p)->data=s->data;
if(q!=(*p))
q->rchild=s->rchild;
else
q->lchild=s->lchild;
free(s);
}
return TRUE;
}
//删除指定结点
Status DeleteBST(BiTree *T,TElemType key)
{
if(!T)
return FALSE;
else
{
if(key==(*T)->data)
return Delete(T);
else if(key<(*T)->data)
DeleteBST(&(*T)->lchild, key);
else
DeleteBST(&(*T)->rchild, key);
return TRUE;
}
}
//中序遍历输出
void InOrderTraverse(BiTree T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("%d ",T->data);
InOrderTraverse(T->rchild);
}
}
int main()
{
printf("sfd\n");
BiTree T = NULL,P=NULL;
for(int i=0;i<5;i++)
{
int e;
scanf("%d",&e);
InsertBST(&T, e);
}
printf("中序遍历结果:");
InOrderTraverse(T);
printf("\n");
printf("查找元素6的结果:");
SearchBST(T, 6, NULL, &P);
DeleteBST(&T, 5);
printf("删除元素5的中序遍历结果:");
InOrderTraverse(T);
return 0;
}
/* 测试
5 4 3 2 1
中序遍历结果:1 2 3 4 5
查找元素6的结果:查找失败
删除元素5的中序遍历结果:1 2 3 4
*/