二叉排序树(BST)删除节点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉排序树(BST)删除节点相关的知识,希望对你有一定的参考价值。

参考技术A 定义:

空树或满足下列性质的二叉树:

1)若它的左子树不空,则左子树所有的关键字的值均小于根关键字的值

2)若它的右子树不空,则右子树所有的关键字的值均大于根关键字的值

3) 左右子树又各是一颗二叉排序树

中序遍历结果是一个增序序列

比较难搞的是BST删除节点

分析如下:

1)首先找到那个节点获取节点的指针位置和父节点指针位置

2)通过这两个指针进行判断获取删除的方案

设目标节点为P

(1)P无子树=>P是叶子节点

(2)P有单子树

(3)P有双子树

BST(二叉排序树)的插入与删除

值得一说的是删除操作,删除操作我们分为三种情况:

1.要删的节点有两个孩子:

  找到左子树中的最大值或者右子树中的最小值所对应的节点,记为node,并把node的值赋给要删除的节点del,然后删除node

实际上真正删除的是node,del只是发生了一次值的替换。

为了方便理解和操作,我们把两个孩子的情况放在最前面,这样经过以上处理后,该节点就会变成情况2或者情况3 ,接下爱这行这两种情况的代码。

2.要删的节点有一个孩子

r判断要删除的节点del是其父亲father的左孩子还是右孩子,以是father的左孩子为例,del是father的左孩子,接下来判断del是否有左孩子,

如果有,则father的左孩子变成del的左孩子,如果没有,则father的左孩子变成del的右孩子。

3.要删的节点没有孩子

即为当情况2 del的左孩子右孩子为空的时候

#include<stdio.h>
#include<stdlib.h>
typedef struct Tree
{
	int data;
	Tree*right;
	Tree*left;
}BinaryTree;
void insert(BinaryTree **p,int e)
{
	BinaryTree *temp=(BinaryTree*)malloc(sizeof(BinaryTree));
	temp->data=e;
	temp->left=NULL;
	temp->right=NULL;

	if(*p==NULL)
	{
		*p=temp;
		return ;
	}
	BinaryTree*root=*p;
	while(1)
	{
		if(e<root->data)
		{
			if(root->left)
			{
				root=root->left;
			}
			else
			{
				root->left=temp;
				break;//完成插入操作了
			}

		}
		else if(e>root->data)
		{
			if(root->right)
			{
				root=root->right;

			}
			else
			{
				root->right=temp;
				break;
			}
		}
	}
}
void  FindNode(BinaryTree* p,BinaryTree **del,BinaryTree**father, int e)//我们在删除操作中不仅需要知道要删除哪个节点,还要知道要删除节点的父亲
{                                          //return无法返回两个值,要实现返回两个值,我们在这里采用二级指针
	while(1)                                                                    //实际上也可以通过结构体封装来完成同时返回两个值
	{
		if(e<p->data)
		{  
			*father=p;//每次都记录一下父亲
			p=p->left;
		}
		else if(e>p->data)
		{
			*father=p;
			p=p->right;
		}
		else if(e==p->data)
		{
			*del=p;return ;	
		}
	}
}
void deleteNode(BinaryTree **p,int e)//
{
	if(*p==NULL) return ;
	BinaryTree *root=*p;
	BinaryTree *del=NULL;
	BinaryTree *father=NULL;
	BinaryTree *pmark=NULL;
	FindNode(root,&del,&father,e);
	if(del->left&&del->right)
	{
		pmark=del;//标记要删除的点
		father=del;
		del=del->left;
		while(del->right)
		{
			father=del;
			del=del->right;
		}
		pmark->data=del->data;
	}
	//接下来分析有一个或者没有孩子的情况
	//被删节点 是根
	if(father==NULL)//??
	{
		*p=del->left?del->left:del->right;
		free(del);
		return ;
	}
	else
	{//不用在写判断条件了,走到这说明就是一个或者没有孩子,只需要判断是哪边的孩子就可
		if(del==father->left)
			father->left=del->left?del->left:del->right;
		else if(del==father->right)
			father->right=del->left?del->left:del->right;
		free(del);

	}
}
void inorder(BinaryTree *p)
{
	if(p==NULL) return ;
	//递归要有结束条件
	inorder(p->left);
	printf(" %d ",p->data);
	inorder(p->right);
}
void preorder(BinaryTree *p)
{
	if(p==NULL) return ;
	//递归要有结束条件
	
	printf(" %d ",p->data);
	preorder(p->left);
	preorder(p->right);
}
int main()
{
	int m;
	BinaryTree *p=NULL;
	int a[10];
	int i;
	scanf("%d",&m);
	for(i=0;i<m;i++)
	{
		scanf("%d",&a[i]);
	}
	for(i=0;i<m;i++)
	{
		insert(&p,a[i]);
	}
	preorder(p);
	printf("\n");
	inorder(p);
	deleteNode(&p,9);
	preorder(p);
	printf("\n");
	inorder(p);
	return 0;
}

  

以上是关于二叉排序树(BST)删除节点的主要内容,如果未能解决你的问题,请参考以下文章

二叉排序树

BST(二叉排序树)的插入与删除

二叉排序树

二叉排序树(BST)

树——二叉排序树(BST)

树和二叉树总结—BST二叉排序树