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;
}