首先提一句什么是二叉搜索树:对于树中的每个结点P,其左孩子中所有值小于该节点的值,而其右孩子中所有值大于该节点的值。前者称作前驱,后者称作后继。利用这种大小特性可以很方便查找到需要的节点。
二叉搜索树的插入:插入某一节点,值为v,从根节点作为起始,如果v小于当前节点的值,则记录的当前节点的位置作为父节点,把当前节点指针指向其左节点继续判断;否则,记录当前节点的位置,然后指针指向其右节点。重复上述操作直至指针的值为空。然后对比父节点与新增节点的大小以选择新增节点的左右位置。
typedef struct BinaryTree
{
int data;
struct BinaryTree *lchild;
struct BinaryTree *rchild;
};
void Insert(BinaryTree **root,int data)
{
BinaryTree *p=*root;
BinaryTree *parent=NULL;
if(NULL==p)
{
p=(BinaryTree*)malloc(sizeof(BinaryTree));
p->data=data;
p->lchild=NULL;
p->rchild=NULL;
*root=p;
return;
}
while(p!=NULL)
{
parent=p;
if(data<p->data)
p=p->lchild;
else
p=p->rchild;
}
p=(BinaryTree*)malloc(sizeof(BinaryTree));
p->data=data;
p->lchild=NULL;
p->rchild=NULL;
if(data<parent->data)
parent->lchild=p;
else
parent->rchild=p;
}
搜索:
bool Search(BinaryTree *root,int data)
{
if(root==NULL) return false;
BinaryTree *p=root;
while(p!=NULL)
{
if(p->data==data) return true;
else if(data<p->data) p=p->lchild;
else p=p->rchild;
}
return false;
}
删除操作:删除节点要分2个情况考虑:
1. P(P为待删除节点指针)有两个子节点:采用子节点替换的方法,A、B任选
A. 从其所有前驱节点中查找最大的节点(这样做的目的是保证替换后,在其所有前驱节点不能有大于其自身的节点),具体做法是:从P的左孩子开始(包括P的左孩 子)循环遍历右孩子,直到找到第一个右孩子为空的节点,将找到的节点的前驱作为其父节点的后继,把找到的节点替换P节点;
B. 从其所有后继节点中查找最小的节点(这样做的目的是保证替换后,在其所有后继节点不能有小于其自身的节点),具体做法是:从P的右孩子开始(包括P的右孩 子)循环遍历左孩子,直到找到第一个左孩子为空的节点,将找到的节点的后继作为其父节点的前驱,把找到的节点替换P节点;
2. P最多有一个子节点:P的左子节点不为空,将P的父节点与P的左子节点相连,删除P;P的右子节点不为空,将P的父节点与P的右子节点相连,删除P;P没有子节点,
直接删除P即可。若P是根节点则需要处理根节点指针。
void Delete(BinaryTree **root,int data)
{
BinaryTree *p=*root;
BinaryTree *parent=p;
if(NULL==p) return;
bool flag=false;
while(!flag&&p!=NULL)
{
if(data==p->data)
flag=true;//找到节点
else if(data<p->data)
{
parent=p;
p=p->lchild;
}
else
{
parent=p;
p=p->rchild;
}
}
if(!flag)
{
printf("未找到该节点.\n");
return;
}
if(p->lchild!=NULL&&p->rchild!=NULL)
{
// 左右子节点均存在
BinaryTree *temp=p->rchild;
BinaryTree *temp_parent=p;
while(temp->lchild!=NULL)
{
temp_parent=temp;
temp=temp->lchild;
}
temp_parent->lchild=temp->rchild;
p->data=temp->data;
free(temp);
}
else
{
// 最多有一个子节点
if(p->lchild!=NULL)
{
if(parent->lchild==p)
parent->lchild=p->lchild;
else if(parent->rchild==p)
parent->rchild=p->lchild;
else
{
//处理根节点
*root=p->lchild;
parent=NULL;
}
free(p);
}
else if(p->rchild!=NULL)
{
if(parent->lchild==p)
parent->lchild=p->rchild;
else if(parent->rchild==p)
parent->rchild=p->rchild;
else
{
*root=p->rchild;
parent=NULL;
}
free(p);
}
else
{
if(parent->lchild==p)
parent->lchild=NULL;
else if(parent->rchild==p)
parent->rchild=NULL;
else
{
*root=NULL;
parent=NULL;
}
free(p);
}
}
}
样例输入:提供一个整型数组用于构建二叉搜索树{10,5,28,3,15,20,13,18,16,19},删除值为15的节点