数据结构二叉查找树BST的创建添加以及删除代码(C语言实现)

BST(Binary Search Tree)二叉搜索树的特点

如果左子树不为空,那么他的左子树的值小于根节点(或父节点)的数值。右子树恰恰相反,如果右子树不为空,那么他右子树的值大于根节点(或父节点)的值。
并且,根节点的左右子树分别也都满足BST的特点,即左右子树单拿出来也是二叉搜索树。

二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。

二叉树的创建和添加代码如下:


#include<stdio.h>
#include<stdlib.h>

typedef strcut bst
{
	int nValue;
	struct bst* pLeft;
	struct bst* pRight;
}BST;

void AddNode(BST**pRoot,int nNum)
{
	BST*pTemp = NULL;
	pTemp = (BST*)malloc(sizeof(BST));
	pTemp->nValue = nNum;
	pTemp->pLeft = NULL;
	pTemp->pRight = NULL;
	if(*pRoot == NULL)
	{
		*pRoot = pTemp;
	}
	BST*pNode = *pTree;
	while(pNode)
	{
		if(pNode->nValue > nNum)
		{
			//左节点为空
			if(pNode->pLeft == NULL
			{
				//添加到左节点
				pNode->pLeft = pTemp;
				return;
			}
			pNode = pNode->pLeft;
		}
		if(pNode->nValue < nNum)
		{
			//右节点为空
			if(pNode->pRight == NULL
			{
				//添加到右节点
				pNode->pRight = pTemp;
				return;
			}
			//移动
			pNode = pNode->pRight;
		}
		//其他情况报错
		else
		{
			printf("data error");
			//将申请的Ptemp删除
			free(pTemp);
			pTemp = NULL;
		}
		
	}
}

BST* CreateBST(int arr[],int nLength)
{
	if(arr == NULL || nLength <= 0)
		return ;
	int i;
	BST*pRoot = NULL;
	for(i = 0;i < nLength; i++)
	{
		AddNode(&pRoot,arr[i]);
	}
	return pRoot;
}

BST的删除操作:
当我们删除BST的节点时,有以下几种情况:
1.要删除的节点没有左右子树。
这种情况下,只是删除了叶子节点,只需将该节点直接删除即可;
2.要删除的节点只有一个孩子。
这种情况下,只需将子节点和要删除的父节点连接,再将要删除的节点删除即可。
3.要删除的节点有两个孩子。
这种情况下,先寻找要删除的节点的左孩子的最右节点,或者右孩子的最左节点,将他的值覆盖到要删除的节点,此时,对于我们来说,需要删除的便是叶子节点(即左孩子的最右节点,或者右孩子的最左节点)。如果左孩子的最右节点为空,那么将要删除的节点的值改编为他的左孩子,再将左孩子删除。
注意:我们需要删除节点的父节点。

代码如下:

//此函数寻找被删除的节点 和他的夫节点
void Search(BST*pTree,int nNum;BST**pFather,BST**pDel)
{
	while(pTree)
	{
		if(pTree->nValue == nNum)
		{
			*pDel = pTree;
			return;
		}
		if(pTree->nValue < nNum)
		{
			*pFather = pTree;
			pTree = pTree->pRight;
		}
		else 
		{
			*pFather = pTree;
			PTree = pTree->pLeft;
		}
	}
	*pFather = NULL;
	return;
}
void DelNode(BST**pTree,int nNum)
{
	if(pTree == NULL)
		return;
		
	BST*pDel = NULL;
	BST*pFather = NULL;
	Search((*pTree),nNum,&pFather,&pDel);
	
	//两个孩子的情况
	BST*pMark = NULL;
	if(pDel->pLeft != NULL && pDel->pRight != NULL)
	{
		//找左孩子的最右
		//先向左移动一个,但是父节点要先等于pDel 然后才可以移动
		pFather = pDel;					
		pMark = pDel;					//标记节点 做值的覆盖
		pDel =pDel->pLeft;
		while(pDel->pRight)
		{
			pFather = pDel;
			pDel = pDel->pRight;
		}
		//找到后,覆盖掉
		pMark->nValue = pDel->nValue;
	}	
	
	//一个孩子或者没有孩子
	//根
	if(pFather == NULL)
	{
		*pTree = pDel->pLeft ? pDel->pLeft : pDel->pRight;
		free(pDel);
		pDel = NULL;
		return;
	}
	//非根
	if(pDel == pFather->pLeft)
	{
		pFather->pLeft = pDel->pLeft ? pDel->pLeft : pDel->pRight;
	}
	else
	{
	 	pFather->pRight = pDel->pLeft ? pDel->pLeft : pDel->pRight;
	}

	free(pDel)
	pDel = NULL;

	return;	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值