二叉查找树的定义以及几个基本操作

二叉查找树是一种特殊的二叉树,一般数据域都是数值类型的元素,原因是二叉查找树基本性质决定了,在二叉查找树中的任意结点,其数据域的数值一定大于它的左子树的所有结点,也小于它的右子树的所有结点!!!所以,是可以比较的数据域才是二叉查找树的存在意义!


这里我写了几个二叉查找树的方法,前几个比较简单,唯一有点难度的是删除结点的操作!


如果待删除的结点是叶子结点,非常好办,删之即可!

如果待删除的结点是非叶子结点,就稍微麻烦一点。非叶子结点也分为两种:有一个子结点和有两个子结点的情况,她们也要分开讨论:


我直接用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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值