二叉排序树-C语言

二叉排序树(BST)(二叉搜索树,二叉查找树):

或者是一棵空树,或者是具有下列性质的二叉树:

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

2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值

3. 它的左、右子树也分别为二叉排序树。

 

//定义树的结构体
typedef struct BiNode {
	int data;
	struct BiNode *lchild, *rchild;
}BiTNode;
void InitBST(BiTNode *root)
{
	if (root == NULL)return;
	//测试用例
	BiTNode *n[10];
	for (int i = 0; i < 10; i++)
	{
		n[i] = (BiTNode*)malloc(sizeof(BiTNode));
		n[i]->data = i;
	}
	root->lchild = n[3];
	root->rchild = n[7];
	n[3]->lchild = n[1];
	n[3]->rchild = n[4];
	n[7]->lchild = n[6];
	n[7]->rchild = n[9];

	n[1]->rchild = NULL;
	n[1]->lchild = NULL;
	n[4]->rchild = NULL;
	n[4]->lchild = NULL;
	n[6]->rchild = NULL;
	n[6]->lchild = NULL;
	n[9]->rchild = NULL;
	n[9]->lchild = NULL;
}	

//排序树查找算法
/*
 1.若root是空树,则搜索失败,否则:

 2.若key等于root的的数据域之值,则查找成功;否则:

 3.若key小于root的数据域之值,则搜索root左子树;否则:

 4.查找右子树。
 参数lastT表示最后一次搜索的到的结点(用在下面Insert功能中)
*/
BiTNode *SearchBST(BiTNode *root, int key,BiTNode **lastT)
{
	if (root == NULL)
	{
		return NULL;
	}
	else if (root->data == key)
	{
		return root;
	}
	else if (root->data > key)
	{
		*lastT = root;//保存上一次遍历的值结点
		return SearchBST(root->lchild, key, lastT);
	}
	else
	{
		*lastT = root;//保存上一次遍历的结点
		return SearchBST(root->rchild, key, lastT);
	}
}

//当存在已插入的元素时返回0,否则返回1
int InsertBST(BiTNode *root, int key)
{
	BiTNode *lastT = NULL;//保存上次搜索最后一次遍历的元素(一般用在未找到时,因为只有未找到给定元素才进行插入操作)
	if (!SearchBST(root, key, &lastT))//如果未找到元素
	{
		BiTNode *newNode = (BiTNode*)malloc(sizeof(BiTNode));//为即将要插入的新结点开辟空间
		newNode->data = key;
		newNode->lchild = newNode->rchild = NULL;

		if (lastT->data > key)
		{
			lastT->lchild = newNode;
		}
		else
		{
			lastT->rchild = newNode;
		}
		return 1;
	}
	return 0;
}

//删除一个结点
/*	1,若结点为叶子结点,那么直接调整其父结点的指向为空即可。

	2,若结点的只有左子树或者右子树不为空(左右子树有一个为空,一个不为空),那么只需要根据要删除的元素在其父节点的位置来判断,
如删除节点只存在左子树,只需把子树重新连接到父节点空出来的位置就可以了。

	3,若结点的左右结点都存在,找到被删除节点(DN)的左子树(DNL),该节点(DNL)一直往右走的结点(DNLR)(这个元素是被删除节点左子树中值最大的节点)
移动该节点(DNLR)的值到要删除结点(DN)的位置。然后再删除找到该节点(DNLR)位置即可。
*/
int Delete(BiTNode *node);
int DeleteBST(BiTNode **root, int key)
{
	BiTNode *lastptr = NULL;
	if ((*root)->data == key)
	{
		Delete(root);
		return 1;
	}
	else if ((*root)->data < key)
	{
		DeleteBST(&(*root)->rchild, key);
	}
	else if ((*root)->data > key)
	{
		DeleteBST(&(*root)->lchild, key);
	}
	return 0;
}
int Delete(BiTNode **node)
{
	BiTNode *tmp,*tmpleft;
	if ((*node)->lchild == NULL)//如果删除结点的左子树为空,只需重接被删除结点的右子树
	{
		tmp = *node; *node = (*node)->rchild; free(tmp);
	}
	else if ((*node)->rchild == NULL)//重接左子树
	{
		tmp = *node; *node = (*node)->lchild; free(tmp);
	}
	else//左右子树都不为NULL//1.从被删除的结点的左子树找到最大的结点替换被删除的结点。2,将第一步找到的结点的左子树重接到他的父节点位置(找到的那个结点的位置)
	{
		BiTNode *MaxVal = NULL;
		MaxVal = (*node)->lchild;//tmp就是那个被找到的结点,它的val最大
		while (MaxVal->rchild != NULL)
		{
			MaxVal = MaxVal->rchild;
		}
		tmp = *node;
		(*node)->data = MaxVal->data;
		Delete(&MaxVal);//删除那个被找到结点的左子树
		free(MaxVal);
	}
}

注意:

  • 以上删除节点时通过二级指针传参修改了父节点对自己的指向,无需在树的结构体中定义该节点的父节点。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值