剑指offer第二版——面试题8(java)

面试题8:二叉树的下一个节点

题目描述: 
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针

分析: 
根据中序遍历的特点,要找到一个节点的下一个节点的三种情况: 

情况一、有右子树,这时只需要把其右孩子作为下一个遍历的(并不是要找的)节点,然后沿着该节点的左子树(如果有的话)

出发,直到遇到叶子节点,那么该叶子节点就是其下一个要找的节点; 

情况二:没有右子树

    ① 该节点是其父节点的左孩子,如果是则其下一个要找的节点是其父节点; 

    ② 不是其父节点的左孩子,则把其父节点作为下一个遍历的节点,向上回溯,直到找到节点没有父节点或者节点是其父节点的左孩子为止,该位置的父节点则为寻找的点

代码:

// 2019-06-14
public class Q8 {
	public static void main(String[] args) {
		ListNode1 node = getTree();
		ListNode1 next = getNext(node);
		// 4 2 8 5 9 1 6 3 7 
		if(next!=null) {
			System.out.println(next.val);
		}
	}
	
	public static ListNode1 getNext(ListNode1 root) {
		// 有右子树
		if(root.right!=null) {
			ListNode1 temp = root.right;
			while(temp.left!=null) {
				temp = temp.left;
			}
			return temp;
		}
		
		// 无右子树 但节点是其父节点的左节点
		if(root.right==null && root.father.left==root) {
			return root.father;
		}
		
		// 无右子树 节点是父节点的右子树
		if(root.right==null && root.father.right==root) {
			ListNode1 temp = root.father;
			while(temp.father!=null) {
				if(temp.father.left==temp) {
					return temp;
				}
				temp = temp.father;
			}
		}
		
		System.out.println("There are not next node");
		return null;
	}
}
// 2019-03-11
public class Q8 {
	public static void main(String[] args) {
		// 构造第二版书上P65的树,a~i按层从上到下,为1~9
		ListNode head1 = new ListNode(1, null);
		ListNode node2 = new ListNode(2, head1);
		ListNode node3 = new ListNode(3, head1);
		head1.left = node2;
		head1.right = node3;
		ListNode node4  = new ListNode(4, node2);
		ListNode node5  = new ListNode(5, node2);
		node2.left = node4;
		node2.right = node5;
		ListNode node6  = new ListNode(6, node3);
		ListNode node7  = new ListNode(7, node3);
		node3.left = node6;
		node3.right = node7;
		ListNode node8  = new ListNode(8, node5);
		ListNode node9  = new ListNode(9, node5);
		node5.left = node8;
		node5.right = node9;
		
		// 显示中序遍历
		head1.oTo(head1);

		
		ListNode node = findNext(node7);
		if(node == null) {System.out.println("null");}
		else {
			System.out.printf("\nresult:%d",node.val);
		}
	}
	
	public static ListNode findNext(ListNode node) {
		if(node == null) {
			return null;
		}
		ListNode temp = null;;
		
		// 情况一:存在右子树——寻找右子树中的最左节点
		if(node.right!=null) {
			temp = node.right;
			System.out.printf("\n存在右子树 :%d",temp.val);
			while(temp.left!=null) {
				temp = temp.left;
			}
			return temp;
			
		}
		// 情况二:不存在右子树,此中分两类
		else{
			temp = node;
			System.out.println("\n没有右子树");
			
			// 如果该结点没有父节点,则中序遍历中为最后一个节点,返回null
			if(temp.father==null) {
				return null;
			}
			
			// 如果该结点有父节点,寻找上层结点中,第一个为自己父节点的左节点的位置,并返回该结点的父节点
			else {
				while(temp!=null) {
					if(temp.father!=null) {
						if(temp.father.left == temp) {
							return temp.father;
						}else {
							temp = temp.father;
						}
					}
					temp = temp.father;
				}
				return null;
			}
		}
	}
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值