C. DS二叉排序树之删除

目录

题目描述

思路分析

AC代码


题目描述

给出一个数据序列,建立二叉排序树,并实现删除功能

对二叉排序树进行中序遍历,可以得到有序的数据序列

输入

第一行输入t,表示有t个数据序列

第二行输入n,表示首个序列包含n个数据

第三行输入n个数据,都是自然数且互不相同,数据之间用空格隔开

第四行输入m,表示要删除m个数据

从第五行起,输入m行,每行一个要删除的数据,都是自然数

以此类推输入下一个示例

输出

第一行输出有序的数据序列,对二叉排序树进行中序遍历可以得到

从第二行起,输出删除第m个数据后的有序序列,输出m行

以此类推输出下一个示例的结果

输入样例

1
6
22 33 55 66 11 44
3
66
22
77

输出样例

11 22 33 44 55 66 
11 22 33 44 55 
11 33 44 55 
11 33 44 55 

提示

当删除数据不在序列中,那么删除操作等于不执行,所以输出序列不变化

思路分析

用插入的方法先创建二叉排序树,插入数据的时候,从根结点开始比较,若数据大于结点的数据,就与右孩子比。若数据小于该结点的数据,就与左孩子比较。如果是null,就可以插入了。是一个递归函数。

然后这道题的重点就是删除。在二叉排序树中删除结点,还要保证删除后的树还是二叉排序树,结点的左孩子都要小于结点本身,右孩子都要大于结点本身。总结下来有三种情况:删除的结点是叶子结点,删除的结点只有左(右)孩子,删除的结点是中间结点。

1.删除的是叶子结点。这是最简单的情况,只需要查找到谁的孩子是它,把父亲的指针指向NULL;

2.删除的结点只有左(右)孩子。这种情况先找到父亲,把父亲指向孩子的指针指向它的左(右)孩子就行。

3.删除的结点是中间结点。最复杂的情况。需要找到中序输出时该结点的直接前驱u,用直接前驱替代它,再删去那个直接前驱(这个直接前驱必是第一种或者第二种情况,别人就不是它的直接前驱),调用前面写好的两种方法删除就好了。

AC代码

#include<iostream> 
#include <queue> 
using namespace std;

class node{
		public:
		int data;
		node *lchild,*rchild;
		node():data(0){
			lchild=NULL;
			rchild=NULL;
		}
		friend class tree;
};
class tree{
	private:
		node *root;
	public:
		tree(){
			root=new node();
		}
		
		node * getroot(){
			return root;
		}
		
		void create(int n){
			int x;
			while(n--){
				cin>>x;
				insert(x,root);
			}
		}
		
		node* insert(int x,node *r){
		if(r->data==0){
			r->data=x;
		}
		else if(x>r->data&&r->rchild!=NULL){
			insert(x,r->rchild);
		}
		else if(x<r->data&&r->lchild!=NULL){
			insert(x,r->lchild);
		}
		else if(x>r->data){
			node *p=new node();
			p->data=x;
			r->rchild=p;
		}
		else{
			node *p=new node();
			p->data=x;
			r->lchild=p;
		}
		return r; 
		}
	
		int search(int x,node *r){
			if(r->data>x&&r->lchild==NULL) return -9999;
			if(r->data<x&&r->rchild==NULL) return -9999;
			if(r->data==x) {
			if(r->lchild==NULL&&r->rchild==NULL) return 1;     //叶子结点 
			else if((r->lchild==NULL&&r->rchild!=NULL)||(r->lchild!=NULL&&r->rchild==NULL)) return 2;   //只有左(右)子树的结点 
			else return 3;//中间的结点 
			}
			if(r->data>x) return search(x,r->lchild);
			if(r->data<x) return search(x,r->rchild);
		}
		
		void tihuan(int x,int front,node *r){
			if(r->data==x) r->data=front;
			if(r->lchild!=NULL) tihuan(x,front,r->lchild);
			if(r->rchild!=NULL) tihuan(x,front,r->rchild); 
		}
		
		void delete_leaf(int x,node *r){
			if(r->rchild!=NULL&&r->rchild->data==x) {
				r->rchild=NULL;
			}
			else if(r->lchild!=NULL&&r->lchild->data==x){
				 r->lchild=NULL;
			}
			else {
			if(r->rchild!=NULL)	delete_leaf(x,r->rchild);
			if(r->lchild!=NULL)	delete_leaf(x,r->lchild);
			}
		}
		void delete2(int x,node *r){
			if(r->rchild->data==x) {
				if(r->rchild->lchild!=NULL) r->rchild=r->rchild->lchild;
				else r->rchild=r->rchild->rchild;
			}
			else if(r->lchild->data==x) {
				if(r->lchild->lchild!=NULL) r->lchild=r->lchild->lchild;
				else r->lchild=r->lchild->rchild;
			}
			else {
				delete_leaf(x,r->rchild);
				delete_leaf(x,r->lchild);
			}
		}
		void delete3(int x){
			int front=find_front(x);
		//	cout<<front<<endl;
			int tag=search(front,root);
			if(tag==1) delete_leaf(front,root);
			else delete2(front,root);
			tihuan(x,front,root);
		}
		int find_front(int x){
	     	queue<int> q;
			zhongxu2(root,q);
			int a[q.size()];
			
			for(int i=0;i<q.size();i++)
			{
				a[i]=q.front();
				q.pop();
			}
		
			for(int i=0;i<q.size();i++)
			{
				if(a[i]==x) return a[i-1];
			}
		}
		void Delete_func(int m){
		int x;
		while(m--){
			cin>>x;
			int tag=search(x,root);
			if(tag==1){
			//	cout<<"是叶子结点"<<endl;
				delete_leaf(x,root);
				zhongxu(root);
			}
			else if(tag==2){
			//	cout<<"是有一边结点"<<endl;
				delete2(x,root);
				zhongxu(root);
			}
			else if(tag==3){
		//		cout<<"是两边都有的结点"<<endl;
				delete3(x);
				zhongxu(root);
			}
			else
			zhongxu(root);
			
			cout<<endl;
		}	
		}
		void zhongxu(node* r){
			if(r->lchild!=NULL) zhongxu(r->lchild);
			cout<<r->data<<" ";
			if(r->rchild!=NULL) zhongxu(r->rchild); 
		}
		void zhongxu2(node* r,queue<int>& q){
			if(r->lchild!=NULL) zhongxu2(r->lchild,q);
			q.push(r->data);
			if(r->rchild!=NULL) zhongxu2(r->rchild,q); 
		}
};
int main(){
	int t,n,m;
	cin>>t;
	tree Mytree;
	while(t--){
		cin>>n;
		Mytree.create(n);
		Mytree.zhongxu(Mytree.getroot());
		cout<<endl;
		cin>>m;
		Mytree.Delete_func(m);
	}
	return 0;
}

有错误欢迎指正!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值