(数据结构)二叉排序树的插入、删除

关于插入不多说,主要讲讲删除操作的第三种情况吧。
前面的两种情况比较简单,包含了只有左或者只有右还有左右都没 有的
第三个情况就比较复杂,左右子树都存在,想删除这个节点(设为P)我们采 用取代的方法,在P的左右子树里面找到
合适的一个节点代替它,根据二叉排序树的特点,可以找P的左子树中最大 的或者右子树中最小的,这里我们讲讲前者。

假设一个二叉排序树如图:
我们要删除节点47,执行玩第50行时P,q,s分别指向47,47,35
在这里插入图片描述

跳出while循环时,P不变,s指向37,q一直指向s的父节点,即35,如图:
在这里插入图片描述
此时我们找到了P左子树最大的了(s所指)之后再用37替换47
在这里插入图片描述
再看第57行,很明显P!=q,所以将s的左节点给q的右节点在这里插入图片描述
再释放掉s就可以了
在这里插入图片描述
这样就成功删除了,不过如果q==P呢,那也好办,如果q=P,说明没有进入while循环,那直接将s的左子树给q的左子树就成功删除s了,如图
在这里插入图片描述
上代码:

#include<bits/stdc++.h>
using namespace std;
typedef struct BiTNode{
	int data;
	struct	BiTNode *lchild,*rchild;
}BiTNode,*BiTree; 

bool Search(BiTree T,int key,BiTree f,BiTree &p){//查找,f指向T的父节点,如果T=NULL此时p=NULL,如果找到p=T(此时T是叶子结点,T->child一定为空) 
	if(!T) {
		p=f;
		return false;
	}
	if(key==T->data){
		p=T;	
		return true;
	}
	else if(key<T->data) Search(T->lchild,key,T,p);
	else if(key>T->data) Search(T->rchild,key,T,p);

}
void Insert(BiTree &T,int key){
	BiTree s,p;	
	if(!Search(T,key,NULL,p)){//没查找到 
		s=(BiTree)malloc(sizeof(BiTNode));
		s->data=key;
		s->lchild=s->rchild=NULL;
		if(!p) T=s;
		else if(key<p->data) p->lchild=s;
		else if(key>p->data) p->rchild=s;	
	}
	else printf("要插入的节点已存在!\n");
	return ; 
}
void InOderTraverse(BiTree T){
	if(T)  {
		InOderTraverse(T->lchild);
		printf("%d ",T->data);
		InOderTraverse(T->rchild);
	}
}
void Detele(BiTree &P){
	BiTree q,s;
	if(!P->lchild) {//无左子节点 
		q=P;P=P->rchild;free(q);
	}
	else if(!P->rchild){//无右子节点  
		q=P;P=P->lchild;free(q);
	}
	else {//有左右子节点 替换 
		q=P;s=P->lchild;
		while(s->rchild){
			q=s;
			s=s->rchild;
		}	
		//q记录的是s的父亲节点 
		P->data=s->data;
		if(q!=P){
			q->rchild=s->lchild;
		}
		else {//如果q==P,就表明s上一级就是P ,此时把s的左给q的左即可 
			q->lchild=s->lchild;
		}
		free(s);
	}
	return ;
}
void DeteleBST(BiTree &T,int key){
	if(key==T->data) Detele(T);
	else if(key<T->data) DeteleBST(T->lchild,key);
	else if(key>T->data) DeteleBST(T->rchild,key);
	return ;
} 
int main(){
	BiTree T = NULL;
	int n,a;
	printf("输入节点数:\n");
	cin>>n;
	printf("分别输入%d个节点\n",n);
	for(int i=1;i<=n;i++){
		cin>>a;
		Insert(T,a);
	}
	printf("中序遍历结果为:\n");
	InOderTraverse(T);
	putchar('\n'); 
	printf("输入要删除的节点\n");
	int k;
	cin>>k;
	DeteleBST(T,k);
	printf("删除后的中序遍历结果为:\n");
	InOderTraverse(T);
	return 0;
	/*
	16
	62 58 47 35 51 29 37 36  49 56 48 50 88 73 99 93
	*/
} 



在这里插入图片描述

  • 2
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nap!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值