您的位置:首页 > 其它

二叉排序树研究

2015-08-19 22:39 316 查看
数据结构中的二叉排序树研究,做个记录。

(1)二叉排序树概念(二叉查找树)

它是一颗空树,或者具有以下性质的二叉树。

a、若它的左子树不为空,则左子树上所有结点值均小于它的根结点的值

b、若它的右子树不为空,则左子树上所有结点值均大于它的根结点的值

c、左右子树有分别是二叉排序树

(2)二叉排序树查找操作

二叉排序树结点结构体:

typedef struct BiTNode          //结点结构体
{
int data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
查找代码如下:

/*********************************************
**功能:递归查找二叉排序树中是否存在key
**T:二叉排序树
**key:键值
**f:指向T的双亲
**p:如果查找成功  指向该数据元素结点       否则指向查找路径上访问的最后一个结点,并返回一个false
*********************************************/
int SearchBST(BiTree T,int key,BiTree f,BiTree *p)
{
if (!T)        //查找不成功
{
*p = f;
return 0;
}
else if (key == T->data)          //找到了键值
{
*p = T;
return 1;
}
else if (key < T->data)           //左子树继续查找
{
return SearchBST(T->lchild,key,T,p);
}
else                             //右子树中继续查找
{
return SearchBST(T->rchild,key,T,p);
}
}
(3)二叉排序树插入操作

/*********************************************
**功能:二叉排序树插入操作,如果二叉排序树中不存在关键字等于key的数据元素时,插入key并返回true,否则返回false
**T:二叉排序树
**key:关键字
*********************************************/
int InsertBST(BiTree *T,int key)
{
BiTree  p,s;           //两个临时变量,p指向查找路径上的最后一个结点;s用于新插入的结点
if (!SearchBST(*T,key,NULL,&p))       //查找不成功时进行插入
{
s = (BiTree)malloc(sizeof(BiTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if (!p)                       //表示一颗空树
{
*T = s;
}
else if (key < p->data)      //插入到左子树
{
p->lchild = s;
}
else                         //插入到右子树
{
p->rchild = s;
}
return 1;
}
else
{
return 0;
}
}
(4)二叉排序树删除操作

删除操作稍微麻烦写,分三种情况讨论

a、待删除结点是叶子结点(直接删除)

b、待删除结点仅有左或者右子树(子承父业)

c、待删除结点左右子树同时存在(找到待删除结点的直接前驱,用直接前驱替换当前点,然后重接左或右子树)

代码如下:

/*********************************************
**功能:二叉排序树删除操作,如果二叉排序树中存在关键字等于key的数据元素时,删除该数据元素结点,并返回true,否则返回false
**T:二叉排序树
**key:关键字
*********************************************/
int DeleteBST(BiTree* T,int key)
{
if (! *T)    //不存在关键字等于key的数据元素
{
return 0;
}
else
{
if (key == (*T)->data)             //找到关键字等于key的结点
{
return Delete(T);
}
else if (key < (*T)->data)
{
return DeleteBST(&(*T)->lchild,key);
}
else
{
return DeleteBST(&(*T)->rchild,key);
}
}
}
真正执行删除操作的是Delete()函数,代码如下:

/*********************************************
**功能:二叉排序树中删除结点p,并重接左右子树
**p:待删除的结点
*********************************************/
int Delete(BiTree *p)
{
//分三种情况讨论:待删除的结点  1、叶结点  2、仅有左或右子树  3、左右子树同时存在
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;         //s指向被删除结点的直接前驱
if (q != *p)
{
q->rchild = s->lchild;     //重接q的右子树
}
else
{
q->lchild = s->lchild;     //重接q的左子树
}
free(s);
}
return 1;
}


测试如下:

/*********************************************
**功能:二叉排序树删除操作,如果二叉排序树中存在关键字等于key的数据元素时,删除该数据元素结点,并返回true,否则返回false
**T:二叉排序树
**key:关键字
*********************************************/
int DeleteBST(BiTree* T,int key)
{
if (! *T)    //不存在关键字等于key的数据元素
{
return 0;
}
else
{
if (key == (*T)->data)             //找到关键字等于key的结点
{
return Delete(T);
}
else if (key < (*T)->data)
{
return DeleteBST(&(*T)->lchild,key);
}
else
{
return DeleteBST(&(*T)->rchild,key);
}
}
}

/*********************************************
**功能:递归打印二叉树,中序遍历
**T:二叉排序树
*********************************************/
void PrintBTree(BiTree T)
{
if (!T) //递归出口
return;
PrintBTree(T->lchild);
printf("%d\t",T->data);
PrintBTree(T->rchild);
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[] = {62,88,58,47,35,73,51,99,37,93};
BiTree T = NULL;
for (int i=0;i<10;++i)
{
InsertBST(&T,a[i]);
}
PrintBTree(T);
DeleteBST(&T,58);
PrintBTree(T);
return 0;
}
结果有图为证:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: