头像

欢迎来到我的博客

分享题解与总结

P5076 普通二叉树

P5076 普通二叉树

P5076 【深基16.例7】普通二叉树(简化版) - 洛谷

题目含义:

  1. Search(x):查询x,并计算x的排名——严格小于x的个数+1

  2. SearchXth():查询排名为x的数(一定有解)

  3. SearchPredecessor(x):找x的前驱

  4. SearchSuccessor(x):找x的后继

  5. Insert(x):插入x

    “本题的数据保证插入前 x 不在集合中”

核心:

数据结构:

struct BSTNode{
	int data;
	int size;
	BSTNode *lchild,*rchild;
};

找前驱和后缀:

  1. 类比二分答案代码
    • root负责寻找目标节点,pre或suc则始终在合法区间,
    • pre∈{小于x的所有可能节点}∪{nullptr},suc∈{大于x的所有可能节点}∪
  2. 注意
    • 初始值,pre=nullptr,suc=nullptr
    • 相等的情况:pre和suc均不应该指向值相等的点
  3. 代码含义:
BSTNode* FindPredecessor(BSTNode* root,int val)
{
	BSTNode* pre=nullptr;
	while(root){
		if(root->data<val){//root及其左子树较小
			pre=root;	  //但属于合法区间
			root=root->rchild;//root尝试最大化
		} 
		else if(root->data>=val){//root及其右子树较大
			root=root->lchild;//尝试缩小root到合法区间		
		}
	}
	return pre;
}

验证:

       5
     /   \
    3      8
  /   \     \
1       4    10
             /
            9

对应样例:

14
5 5
5 3
5 1
5 4
5 8
5 10
5 9
3 8
3 9
4 5
4 3
4 4
4 10
4 8

代码:

struct BSTNode{
	int data;
	int size;
	BSTNode *lchild,*rchild;
};
int q,opt,x;

//查找x,并计算严格小于x的个数(cnt)
BSTNode* Search(BSTNode* root,int val,int& cnt)
{
	if(!root) return root;
	if(root->data>val){
		return Search(root->lchild,val,cnt);
	}
	else if(root->data<val){
		cnt+=1;//root自身 
		if(root->lchild) cnt+=root->lchild->size;//左子树结点数 
		return Search(root->rchild,val,cnt);
	}
	else{
		if(root->lchild) cnt+=root->lchild->size;
		return root;
	}
}

//插入值val的节点 
void Insert(BSTNode* &root,int val)
{
	if(!root){
		root=new BSTNode;
		root->data=val;
		root->size=1;//包括自己 
		root->lchild=nullptr;
		root->rchild=nullptr;
	}
	else if(root->data>val){
		Insert(root->lchild,val);
		root->size++;
	}
	else if(root->data<val){
		Insert(root->rchild,val);
		root->size++;
	}
	//else root->data==val
}

//查询排名为x的数 
void SearchXth(BSTNode* root,int rk)
{
	if(!root) return;
	int leftsize=0;
	if(root->lchild) leftsize=root->lchild->size;
	if(leftsize>=rk){
		SearchXth(root->lchild,rk);
	}
	else if(leftsize+1==rk){
		cout<<root->data<<"\n";
	}
	else{
		SearchXth(root->rchild,rk-leftsize-1);
	}
}

//无论val是否存在,找到小于val的最大节点并返回 
BSTNode* FindPredecessor(BSTNode* root,int val)
{
	BSTNode* pre=nullptr;
	while(root){
		if(root->data<val){
			pre=root;
			root=root->rchild;
		} 
		else if(root->data>=val){
			root=root->lchild;		
		}
	}
	return pre;
}

//无论val是否存在,找到大于vak的最大节点并返回 
BSTNode* FindSuccessor(BSTNode* root,int val)
{
	BSTNode* post=nullptr;
	while(root){
		if(root->data<=val){
			root=root->rchild;
		}
		else if(root->data>val){
			post=root;
			root=root->lchild;
		}
	}
	return post;
}

int main()
{
	int rk,cnt;
	bool flag; 
	BSTNode *root=nullptr;
	BSTNode *px=nullptr,*pre=nullptr,*suc=nullptr;
	cin>>q;
	for(int i=1;i<=q;++i){
		flag=false;
		cin>>opt>>x;
		if(opt==1){
			rk=0;
			px=Search(root,x,rk);
			cout<<rk+1<<"\n"; 
		}
		else if(opt==2){
			SearchXth(root,x);
		}
		else if(opt==3){
			pre=FindPredecessor(root,x);
			if(pre) cout<<pre->data<<"\n";
			else cout<<-2147483647<<"\n";
		}
		else if(opt==4){
			suc=FindSuccessor(root,x);
			if(suc) cout<<suc->data<<"\n";
			else cout<<2147483647<<"\n";
		}
		else{
			Insert(root,x);
		}
	}
	return 0;
}

posted @ 2026-06-29 09:45  king_steph1209  阅读(3)  评论(0)    收藏  举报