二叉查找树是一种特殊的二叉树,一般数据域都是数值类型的元素,原因是二叉查找树基本性质决定了,在二叉查找树中的任意结点,其数据域的数值一定大于它的左子树的所有结点,也小于它的右子树的所有结点!!!所以,是可以比较的数据域才是二叉查找树的存在意义!
这里我写了几个二叉查找树的方法,前几个比较简单,唯一有点难度的是删除结点的操作!
如果待删除的结点是叶子结点,非常好办,删之即可!
如果待删除的结点是非叶子结点,就稍微麻烦一点。非叶子结点也分为两种:有一个子结点和有两个子结点的情况,她们也要分开讨论:
我直接用a代表待删除的结点,这样减少了很多文字叙述,还容易理解!
1、待删除的结点有一个子结点: 这个还是比较容易,用a的双亲结点直接指向a的子结点,然后释放a即可;
2、待删除的结点有两个子结点: 也就是左孩子和右孩子均存在,这才是比较麻烦的,一般的策略是:将a的数据域 = 右子树中的最小数据结点的数据域(设 b),
然后删除这个b结点,由于b是a右子树中的最小数据结点,所以b不可能有左孩子,只可能是有一个右孩子(利用1删之)或者b就是一片叶子,删之十分轻松加愉快,哈哈语病。
好了,上代码,删除结点的操作我会好好注释一下:
#include <stdio.h>
#include <stdlib.h>
/*数据域类型*/
typedef int ElemType;
/*二叉树的结点结构*/
typedef struct _TreeNode
{
ElemType data;
struct _TreeNode * lchild;
struct _TreeNode * rchild;
}TreeNode,*PTree;
/*构造一颗空树*/
void MakeEmpty(PTree * T)
{
if(*T != NULL)
{
MakeEmpty(&(*T)->lchild);
MakeEmpty(&(*T)->rchild);
free(*T);
}
*T = NULL;
}
/*查找结点*/
PTree Find(PTree T,ElemType e)
{
if (T->data == e)
{
return T;
}
else if (T->data > e)
{
return Find(T->lchild,e);
}
else if(T->data < e)
{
return Find(T->rchild,e);
}
}
/*非递归查找最大的结点*/
PTree FindMax(PTree T)
{
if (!T)
{
return NULL;
}
while (T->rchild)
{
T = T->rchild;
}
return T;
}
/*递归查找最小结点*/
PTree FindMin(PTree T)
{
if( !T )
{
return NULL;
}
if(T->lchild == NULL)
{
return T;
}
else
{
return FindMin(T->lchild);
}
}
/*插入结点*/
PTree InsertNode(PTree T, ElemType e)
{
if (!T)
{
T = (PTree)malloc(sizeof(TreeNode));
if(!T)abort();
T->data = e;
T->lchild = NULL;
T->rchild = NULL;
}
if(e < T->data)
{
T->lchild = InsertNode(T->lchild,e);
}
else if(e > T->data)
{
T->rchild = InsertNode(T->rchild,e);
}
return T;
}
/*删除结点*/
PTree DeleteNode(PTree T, ElemType e)
{
PTree tmp;
if(!T)
{
exit(-1); /*空树删个JB*/
}
else if (e<T->data)
{
T->lchild = DeleteNode(T->lchild,e); /*递归左子树*/
}
else if(e>T->data)
{
T->rchild = DeleteNode(T->rchild,e); /*递归右子树*/
}
else if(T->lchild && T->rchild) /*如果待删除的结点左右孩子均存在*/
{
tmp = FindMin(T->rchild); /*找到其右子树中的最小结点*/
T->data = tmp->data;
T->rchild = DeleteNode(T->rchild,T->data); /*删除这个最小数据结点*/
}
else
{/*这个条件里说明是只有一个结点的情况*/
tmp = T; /*临时变量用于释放结点*/
if (T->lchild == NULL) /*只有左孩子*/
{
T = T->rchild;
}
else if( T->rchild == NULL) /*只有右孩子*/
{
T = T->lchild;
}
free(tmp);
}
return T;
}