(第17题)二叉排序树的插入删除和查找(难度系数100)

发布时间:2024年01月06日

难点主要在于删除部分

题目描述487:

二叉排序树的插入删除和查找

pre: 前序遍历
in: 中序遍历
post:后序遍历
insert: 插入,本题中不会出现相同的元素
delete: 删除,删除成功输出TRUE,没有该元素则输出FALSE,删除的方法是如果有左子树,以左子树中最大值作为新的树根,否则,以右子树最小值作为树根。
search: 查找,存在该元素输出YES, 否则输出NO
exit:退出
输入:
输入的第一行为整数 N
接下来一行为N个整数,你需要把这N个整数构建出相应的二叉排序树
之后是一组指令。

输出:
根据相应的指令进行输出。说明:遍历各元素之间用一个空格隔开。

样例输入:
10
31 15 9 5 4 7 8 50 42 2
pre
in
post
delete
15
delete
88
in
search
8
search
222
insert
15
pre
in
post
exit

样例输出:

31 15 9 5 4 2 7 8 50 42
2 4 5 7 8 9 15 31 42 50
2 4 8 7 5 9 15 42 50 31
TRUE
FALSE
2 4 5 7 8 9 31 42 50
YES
NO
31 9 5 4 2 7 8 15 50 42
2 4 5 7 8 9 15 31 42 50
2 4 8 7 5 15 9 42 50 31

注意:在样例中,先把15删除掉了,然后再插入15,观察最开始的三个遍历,和最后的三次遍历,遍历结果是有区别的。

#include<bits/stdc++.h>

using namespace std;

const int N = 1e5+10;

int n,f;
int l[N],r[N];
int a[N],fa[N];//fa[i]为编号i的父节点 
int idx = 1,root = 1;//给每个值编号 

void dfs(int u, int x)//建树过程 
{
	if(l[u]==0 && a[u]>x)
	{
		fa[idx] = u;//记录父节点 
		l[u] = idx; //左孩子为空则先给左孩子 
		return ;
	}
	if(r[u]==0 && a[u]<x)
	{
		fa[idx] = u;//记录父节点 
		r[u] = idx; //有孩子为空,赋给右孩子 
		return ;
	}
	if(a[u] > x) dfs(l[u], x);//u节点大于x 递归左边 
	if(a[u] < x) dfs(r[u], x);//u节点小于x 递归右边 
	
}

void insert(int x)//插入 
{
	if(idx != 1)//寻找父节点 
	dfs(root, x);
	
	a[idx++] = x;//给新节点编号 
}

void pre(int u)//前序输出 
{ 
	if(a[u] == 0) return ;
	cout<<a[u]<<" ";
	pre(l[u]);
	pre(r[u]);
}
void in(int u)//中序输出 
{
	if(a[u] == 0) return ;
	in(l[u]);
	cout<<a[u]<<" ";
	in(r[u]);
}
void post(int u)//后序输出 
{
	if(a[u] == 0) return ;
	post(l[u]);
	post(r[u]);
	cout<<a[u]<<" ";
}

int dfs1(int u)
{
	if(r[u] == 0) return u;
	dfs1(r[u]);
}
int dfs2(int u)
{
	if(l[u] == 0) return u;
	dfs2(l[u]);
}
void del(int u, int x)
{
	if(a[u] == 0) return ;
	if(a[u] == x)
	{
		cout<<"TRUE"<<endl;
		f = 1; //标记为0时说明没找到x 
		if(l[u])
		{
			int u1 = dfs1(l[u]);//找左子树中最大元素 
			if(u == root) root = u1;//换根
		
			if(r[fa[u1]] == u1) r[fa[u1]] = 0;//删除u1父节点存的自己 
			fa[u1] = fa[u];//将u的父节点赋给u1 
			
			if(l[fa[u]] == u) l[fa[u]] = u1;//u为父亲的左孩子,u2替换u 
			if(r[fa[u]] == u) r[fa[u]] = u1;//u为父亲的右孩子,u2替换u 
			
			if(l[u] != u1) l[u1] = l[u];//当u的左节点不为u1时,u1继承u的左孩子 
			
			r[u1] = r[u],fa[r[u]] = u1;//u1继承u的右孩子 
			return ;
		}
		if(r[u])//无左孩子时 
		{
			int u2 = dfs2(r[u]);//找右子树中最小元素
			if(u == root) root = u2;//换根
			
			if(l[fa[u2]] == u2) l[fa[u2]] = 0;//删除u2父节点存的自己
			fa[u2] = fa[u];//将u的父节点赋给u2 
			
			if(l[fa[u]] == u) l[fa[u]] = u2;//若u为父亲的左儿子,u2替换u 
			if(r[fa[u]] == u) r[fa[u]] = u2;//若u为父亲的右儿子,u2替换u 
			
			if(r[u] != u2) r[u2] = r[u];//当u的右节点不为u2时,u2继承u的右孩子 

			l[u2] = l[u],fa[l[u]] = u2;//u2继承u的左孩子 
			return ;
		}
		
		//左右孩子都没有 
		if(l[fa[u]] == u) l[fa[u]] = 0;//若x为父亲的左儿子,删除自己 
		if(r[fa[u]] == u) r[fa[u]] = 0;//若x为父亲的右儿子,删除自己 
		return ;
		 
	}
	if(a[u] > x)del(l[u], x);//u节点大于x 递归左边 
	if(a[u] < x)del(r[u], x);//u节点小于x 递归右边 
}

void search(int u, int x)
{
	if(a[u] == 0) return ;
	if(a[u] == x)
	{
		cout<<"YES"<<endl;
		f = 1;
		return ;
	}
	if(a[u] > x)search(l[u], x);//u节点大于x 递归左边 
	if(a[u] < x)search(r[u], x);//u节点小于x 递归右边 
}

int main()
{
	cin>>n;
	while(n--)
	{
		int x;
		cin>>x;
		insert(x);
	}
	
	while(1)
	{
		string s;
		cin>>s;
		if(s == "pre") pre(root),cout<<endl;
		if(s == "in") in(root),cout<<endl;
		if(s == "post") post(root),cout<<endl;
		if(s == "insert")
		{
			int x;
			cin>>x;
			insert(x);
		}
		if(s == "delete")
		{
			int x;
			cin>>x;
			del(root, x);
			if(f ==0) cout<<"FALSE"<<endl;
			f = 0;
		}
		if(s == "search")
		{
			int x;
			cin>>x;
			search(root, x);
			if(f == 0) cout<<"NO"<<endl;
			f = 0;
		}
		if(s == "exit") break;
	}
}

文章来源:https://blog.csdn.net/Hbj041225/article/details/135415987
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。