二叉搜索树之:【实现找某个节点的后继】【二叉搜索树的性质】

博客介绍了两种常用的建树及找某节点后继节点的方法,分别是 l[],r[] 版本和 Node 版本。同时提醒,因输入询问是节点值,而开的空间是节点编号,需用 mp 存储节点值对应的节点编号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode *father;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL), father(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* p) {
        if(p->right)   //如果右子树存在 
        {
            p=p->right;
            while(p->left)
            {
                p=p->left;
            }
            
            
            return p;
        }
        
        //如果右子树不存在
        /*
        此处就要不断变成父节点,
        直到是父节点的左儿子
        */
        
        while(p->father&&p->father->left!=p)
        {
            p=p->father;
        }
        
        return p->father;
    }
};

常用版本一: l[],r[]版本建树,以及找某节点后继节点

#include <bits/stdc++.h>
using namespace std;
const int N=40;
int l[N],r[N]; 
int fa[N];
int n,a[N];
int root;


void build()
{
	root=4;       //必须要指定一个根节点和它的一个右孩子,不然整个树建立出来不唯一 
	r[root]=6;
	
}

//任意序列建树的过程是找空位插入的过程 
void insert(int &root,int key,int father)
{
	if(!root)    //找到了空位就插入 
	{
		root=key;  
		fa[root]=father;
		 
		//int  root=get_node(key);
		//auto root=new Node(key); 
	    /*
		这里就解释了,为啥root是&root的原因.
	    因为 root改变了,之前传给root的参数也会随之改变 
	    */ 
	} 
	else if(key==root)
	{
		return;
	}
	else if(key>root)
	{
		insert(r[root],key,root);
	}
	else if(key<root)
	{
		insert(l[root],key,root);
	}

}

int find_nex(int p)
{
	//如果有右子树 
	if(r[p])
	{
		p=r[p];
		while(l[p])
		{
			p=l[p];
		}
		
		return p;
	}
	
	//如果没有右子树
	while(fa[p]&&l[fa[p]]!=p)
	{
		p=fa[p];
	}
	
	
	return fa[p];
	
}


void bfs()
{
	queue<int> q;
	q.push(4);
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		
		cout<<t<<" ";
		
		
		if(l[t])
		q.push(l[t]);
		
		if(r[t])
		q.push(r[t]);
	}
}


int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
    }
    
    
    build();
    
    
    for(int i=1;i<=n;i++)
    {
    	insert(root,a[i],0);
	}

	int Q;
	cin>>Q;
	
	
	while(Q--)
	{

	int x;   //输入要找后继的点的key值
	cin>>x;
	
	int nex=find_nex(x);

	printf("%d ",nex);
    } 
    
    cout<<endl;
	
	return 0;
}

常用版本二:Node版本建树,以及找某节点后继节点

注意此处,由于输入的询问是节点值

而我们开的空间是节点编号idx,

所以我们要 通过节点值找到节点编号 

用mp存储一下节点值对应的节点编号

#include <bits/stdc++.h>
using namespace std;
const int N=40,inf=0x3f3f3f3f;
int a[N];
int idx;
int root;
unordered_map<int,int> mp;
struct Node
{
	int l,r;
	int key;
	int fa;
}tr[N];

int get_node(int key)
{
	tr[++idx].key=key;
	return idx;
}


void build()
{
	get_node(4);  //idx变成了1 
	get_node(6);  //idx变成了2 
	root=1;
	mp[4]=root;
	mp[6]=2;
	tr[root].r=2;
}


void insert(int &u,int key,int father)
{
	if(!u)
	{
		u=get_node(key);
		mp[key]=u;
		tr[u].fa=father;
	}
	else if(key==tr[u].key)
	{
		return; 
	}
	else if(key<tr[u].key)
	{
		insert(tr[u].l,key,u);
	}
	else if(key>tr[u].key)
	{
		insert(tr[u].r,key,u);
	}

}

int get_ne(int p)
{
	if(tr[p].r)  //如果右子树存在 
	{
		p=tr[p].r;
		while(tr[p].l)
		{
			p=tr[p].l;
		}
		
		return p;
	}
	
	while(tr[p].fa&&tr[tr[p].fa].l!=p)
	{
		p=tr[p].fa;
	}
	
	p=tr[p].fa;
	
	return p;
	
}

void bfs()
{
	queue<int> q;
	q.push(1);
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		
		cout<<tr[t].key<<" ";
		
		
		if(tr[t].l)
		q.push(tr[t].l);
		
		if(tr[t].r)
		q.push(tr[t].r);
	}
}




int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	
	build();
	
	for(int i=1;i<=n;i++)
	{
		insert(root,a[i],0);
	}
	
	bfs();
	cout<<endl;
	
	int Q;
	cin>>Q;
	while(Q--)
	{
		int x;
		cin>>x;   //输入要找后继的节点值
		int id=mp[x];   //找到该节点值所在的节点编号
		cout<<tr[get_ne(id)].key<<" "; 
	}
	cout<<endl;
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值