前言
二叉排序树,又称为二叉查找树,它具有以下特点:
若它的左子树不空,则左子树所有结点值均小于它的根结点的值
若它的右子树不空,则右子树所有结点值均大于它的根结点的值
它的左,右子树也分别为二叉排序树
可以为空
前提是二叉树,然后也采用了递归的定义方法
二叉排序树中序遍历就一有序表
构造一颗二叉树,就是把一无序的顺序表变为有序的数集,中序遍历二叉排序表就是一有序的表,其目的,并不是为了排序,而是为了提高查找和删除关键字的速度。
1.关键字
二叉排序树的结构体定义和二叉树的结构体定义完全一样
我们存储的数据都是关键字,说白了就是编号,查找的时候也是,因此在本篇中关键字是唯一的,不能出现两个相同的关键字。
2.二叉排序树的查找操作
查找函数,我们定义为一个可递归运行的函数,函数调用时的语句为:SearchBT(T,key,f,p);参数T为一个二叉链表,key为查找的关键字,f为指向T的双亲,p为了得到查找到的结点位置。
代码如下:
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
if(!T)//查找不成功
{
*p = f;
return FALSE;
}
else if(key == T->data)//查找成功
{
*p = T;
return TRUE;
}
else if(key < T->data)
{
return SearchBT(T->lchild,key,T,p);
}
else
return SearchBT(T->rchild,key,T,p);
}
2.二叉排序树的插入操作
只有查得不到的时候,才会进行插入操作,并且将关键字放到树中合适的位置。
代码如下:
Status InsertBT(BTree *T,TElemType key)
{
BTree p,s;
if(!SearchBT(*T,key,NULL,&p))//查找失败
{
s = (BTree)malloc(sizeof(BTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if(!p)
*T = s;//插入s为新的根结点
else if(key < p->data)
p->lchild = s;//插入s为左孩子
else
p->rchild = s;//插入s为右孩子
return TRUE;
}
else
return FALSE;
}
3.二叉排序树的删除操作
删除操作分为三种情况
1.要删除的结点只有左子树,删除后,将他的左子树整个移动到结点位置
2.要删除的结点只有右子树,删除后,将他的右子树整个移动到结点位置
3.要删除的结点既有左子树又有右子树。找到此结点p的有序直接前驱(或直接后驱)s,用s来替换结点p。然后再删除结点s。
代码如下
Status Delete(BTree *p)
{
BTree q,s;
if((*p)->rchild == NULL)//右子树空只需连接它的左子树
{
q = *p; *p = (*p)->lchild; free(q);
}
else if((*p)->lchild == NULL)//左子树空只需连接它的右子树
{
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->lchild;//重接q的右子树
else
q->lchild = s->lchild;//重接q的左子树
free(s);
}
return TRUE;
}
4.总结
二叉排序树其实就是一种把无序的顺序表变为一个有序表,二叉排序树中序遍历就是有序表。
查找利用了类似二分查找的原理
完整代码
以数组
a[10] = {62,88,58,47,35,73,51,99,37,93};
为例:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int TElemType;
typedef struct BTNode
{
TElemType data;
struct BTNode *lchild,*rchild;
}BTNode,*BTree;
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p);//查找算法
Status InsertBT(BTree *T,TElemType key);//插入算法
Status Delete(BTree *p);//删除数据算法
Status DeleteBT(BTree *T,TElemType key);//删除算法
void InOrderTraverse(BTree T);//中序遍历二叉树
int main()
{
int i,x,n,m;
BTree p = NULL;
BTree T = NULL;
int a[10] = {62,88,58,47,35,73,51,99,37,93};
for(i=0;i<10;i++)
{
InsertBT(&T,a[i]);
}
while(1)
{
printf("1.中序遍历 2.删除算法 3.添加算法 4.查找算法\n");
scanf("%d",&n);
switch(n)
{
case 1:
printf("中序遍历二叉树\n");
InOrderTraverse(T);
printf("\n");
break;
case 2:
printf("输入要删除的数\n");
scanf("%d",&x);
m = DeleteBT(&T,x);
if(m==TRUE)
{
InOrderTraverse(T);
printf("\n");
}
else
printf("删除失败\n");
break;
case 3:
printf("输入要添加的数\n");
scanf("%d",&x);
m = InsertBT(&T,x);
if(m==TRUE)
{
InOrderTraverse(T);
printf("\n");
}
else
printf("添加失败\n");
break;
case 4:
printf("输入要查找的数\n");
scanf("%d",&x);
m = SearchBT(T,x,NULL,&p);
if(m==TRUE)
{
printf("查得:%d\n",x);
}
else
printf("查找失败\n");
break;
}
}
}
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
if(!T)//查找不成功
{
*p = f;
return FALSE;
}
else if(key == T->data)//查找成功
{
*p = T;
return TRUE;
}
else if(key < T->data)
{
return SearchBT(T->lchild,key,T,p);
}
else
return SearchBT(T->rchild,key,T,p);
}
Status InsertBT(BTree *T,TElemType key)
{
BTree p,s;
if(!SearchBT(*T,key,NULL,&p))//查找失败
{
s = (BTree)malloc(sizeof(BTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if(!p)
*T = s;//插入s为新的根结点
else if(key < p->data)
p->lchild = s;//插入s为左孩子
else
p->rchild = s;//插入s为右孩子
return TRUE;
}
else
return FALSE;
}
Status Delete(BTree *p)
{
BTree q,s;
if((*p)->rchild == NULL)//右子树空只需连接它的左子树
{
q = *p; *p = (*p)->lchild; free(q);
}
else if((*p)->lchild == NULL)//左子树空只需连接它的右子树
{
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->lchild;
else
q->lchild = s->lchild;
free(s);
}
return TRUE;
}
Status DeleteBT(BTree *T,TElemType key)
{
if(!*T)//要删除的数不存在
return FALSE;
else
{
if(key == (*T)->data)
return Delete(T);
else if(key < (*T)->data)
return DeleteBT(&(*T)->lchild,key);
else
return DeleteBT(&(*T)->rchild,key);
}
}
void InOrderTraverse(BTree T)
{
if(T == NULL)
return;
InOrderTraverse(T->lchild);
printf("%d ",T->data);
InOrderTraverse(T->rchild);
}
运行结果
后记
二叉排序树其实就是为了动态查找而产生的
还记得动态查找是什么吗:
动态查找在查找过程中插入不存在的元素,删除已存在的元素。
今天的内容就是二叉排序树的基本操作及其内容,喜欢我的多多支持哦~