3、找到给定节点在中序遍历序列的下一个节点(剑指offer 08题)

法1、暴力法:这道题我们拿到后,先想最简单的解决办法就是把整棵树按中序遍历一遍,然后就可以找到下一个节点了,但这种方法肯定时间空间开销都很大

法2、这类题说白了就是找规律,一棵树中什么样的节点会是它在中序的下一个节点,我们先动手画一棵节点不要太少的二叉树,然后一个节点一个节点看,用我们的人脑思考它的下一个节点是怎么找到的,最后找到的规律如下

站在所给节点的视角:

1、如果右儿子非空,则下一个节点就是右儿子的最左子孙
2、如果右儿子为空,则回溯至第一个作为“左儿子”的祖先节点处,它的父亲节点就是我们要找的节点
3、如果回溯至根节点还没找到满足步骤2的节点,那么所给节点的下一个节点不存在

接下来只需要把这个过程代码化即可。

/找到给定节点中序遍历的下一个节点 
#include <stdio.h>

struct Node{
	int data;
	Node* left;
	Node* right;
	Node* father;
};

Node* findNext(Node* now){
	if(now==NULL) //如果传来的结点是空则直接返回空 
		return NULL;
	
	if(now->right!=NULL){ //如果右儿子非空,则下一个节点就是右儿子的最左儿子 
		Node* p = now->right;
		while(p->left!=NULL){
			p = p->left;
		}
		return p; 
	}
	
	Node* p = now;        //否则,下一个节点就是作为第一个左儿子的祖先的父亲 
	while(p->father!=NULL && p!=p->father->left ){ //回溯至第一个祖先中第一个左儿子 ,它的父亲就是我们要找的节点 
		p = p->father;
	} 
	return p->father;
	 
}

void create(Node*& T){ //根据带空指针信息的先序序列创建树  
	int x;
	scanf("%d",&x);
	if(x==0)
		return ;
	T = new Node;
	T->data = x;
	T->left = T->right = NULL;
	create(T->left);
	create(T->right);
}

void setFather(Node* T){ //给树里的结点设置父指针,这里没对根节点的父指针赋值,而是在调用之前手动设置根节点父指针为空 
	
	if(T == NULL)
		return;
	if(T->left!=NULL)
		T->left->father = T;
	if(T->right != NULL)
		T->right->father = T;
	setFather(T->left);
	setFather(T->right);
} 

void midOrder(Node* T){ //中序遍历 
	if(T==NULL)
		return;
	midOrder(T->left);
	printf("%d ",T->data);
	midOrder(T->right);
}

int main(){
	Node * root = NULL;
	printf("请输入:\n"); 
	create(root);
	setFather(root);
	root->father = NULL; 
	printf("中序遍历:\n");
	midOrder(root);
	printf("\n"); //这里用1 5 8 0 0 0 6 0 0 做测试 
	printf("1的下一个是%d\n",findNext(root)->data); 
	printf("5的下一个是%d\n",findNext(root->left)->data); 
	printf("8的下一个是%d\n",findNext(root->left->left)->data); 
	if( findNext(root->right) == NULL)
	printf("6的下一个是空\n"); 
	if(findNext(NULL) == NULL)
		printf("0的下一个是空\n"); 
	
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值