首先先看看这个删除节点12后的树,还要保证该平衡二叉树的特性保持不变
删除节点详细分为三类:
第一类.所删除的节点是叶子节点,这样就可以先遍历这个树,然后找到需要删除的节点,把它free掉就好
第二类:就是所删除的节点只有一个左孩子,或者只有一个右孩子,则把该节点的孩子变为它父亲的孩子 ,然后删除这个结点
在这个例子把28删除,就是把30连接到12上
第三类:就是最麻烦的一类,假如我们要删除节点12,直接删除就会破坏了排序二叉树的结构,那么我们想到一个方法,就是把这类转换成第一类,那么重点来了,我们找到要删除的结点后,找到在这个节点左子树的最右的节点或者右子树的最左侧的节点,把这个节点的值覆盖到要删除的节点上,然后删除左子树的最右的节点或者右子树的最左侧的节点,
我们看这个例子:要删除12 先找到以12位根的左子树的最右的节点 就是数字6 ,把6覆盖到节点·12,然后删除节点6
或者找到右子树的最左边的节点 就是该树上的28,把28覆盖到节点12上,再删除28,就变成了第二类删除
代码如下:核心函数Search 和 DelNode
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int nValue;
struct node *pLeft;
struct node *pRight;
}BinatyTree;
void InsertNode(BinatyTree **pTree,int nNum)
{
BinatyTree *pTemp = NULL;
pTemp = (BinatyTree*)malloc(sizeof(BinatyTree));
pTemp->nValue = nNum;
pTemp->pLeft = NULL;
pTemp->pRight = NULL;
//空树
if(*pTree == NULL)
{
*pTree = pTemp;
return;
}
//非空树
BinatyTree *pNode = *pTree;
while(1)
{
if(nNum > pNode->nValue)
{
//去右侧
if(pNode->pRight == NULL)
{
pNode->pRight = pTemp;
return;
}
//向右走
pNode = pNode->pRight;
}
else if(nNum < pNode->nValue)
{
//去左侧
if(pNode->pLeft == NULL)
{
pNode->pLeft = pTemp;
return;
}
pNode = pNode->pLeft;
}
else
{
printf("数据错误.\n");
return;
}
}
}
void CreateBST(int arr[],int nLength,BinatyTree **pTree)
{
if(arr == NULL || nLength <=0)return;
int i;
for(i = 0;i<nLength;i++)
{
InsertNode(pTree,arr[i]);
}
}
void Search(BinatyTree *pTree,int nNum,BinatyTree **pDel,BinatyTree **pFather)
{
while(pTree != NULL)
{
if(pTree->nValue == nNum)
{
*pDel = pTree;
return;
}
else if(pTree->nValue > nNum)
{
*pFather = pTree;
pTree = pTree->pLeft;
}
else
{
*pFather = pTree;
pTree = pTree->pRight;
}
}
}
void DelNode(BinatyTree **pTree,int nNum)
{
if(*pTree == NULL)return;
//查找
BinatyTree *pDel = NULL;
BinatyTree *pFather = NULL;
Search(*pTree,nNum,&pDel,&pFather);
if(pDel == NULL)return;
//分析情况
//两个
BinatyTree *pMark = NULL;
if(pDel->pLeft != NULL && pDel->pRight!= NULL)
{
//找左的最右
pMark = pDel;
//向左走一步
pFather = pDel;
pDel = pDel->pLeft;
while(pDel->pRight != NULL)
{
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;
free(pDel);
pDel = NULL;
return;
}
else
{
pFather->pRight = pDel->pLeft ? pDel->pLeft:pDel->pRight;
free(pDel);
pDel = NULL;
return;
}
}
void Traversal(BinatyTree *pTree)
{
if(pTree == NULL)return;
Traversal(pTree->pLeft);
printf("%d ",pTree->nValue);
Traversal(pTree->pRight);
}
int main()
{
int arr[] = {10,38,2,100,80,15,1,8,16};
BinatyTree *pTree = NULL;
CreateBST(arr,sizeof(arr)/sizeof(arr[0]),&pTree);
Traversal(pTree);
printf("\n");
DelNode(&pTree,10);
Traversal(pTree);
return 0;
}