剑指OFFER笔记_08_二叉树的下一个节点_JAVA实现

题目:二叉树的下一个节点

  • 给定一颗二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?树中的节点除了有两个分别指向左右子节点的指针,还有一个指向父节点的指针。

解题思路

  • 中序遍历,也就是说访问一个二叉树的时候,先访问当前节点的左子树,然后访问当前节点的值,最后访问当前节点的右子树。中序遍历的一个特点就是访问的第一个元素是当前二叉树的最左节点
  • 所以如果要求一个二叉树结点的中序遍历序列的下一个节点,需要分多种情况考虑。
  • 第一种:当前节点有右子树,根据中序遍历的特点,下一个访问的节点就是该节点的右子树的最左节点。这种情况较为简单
  • 第二种:当前节点没有右子树。此时又要分成两类情况考虑。
  • 第二种(1):当前节点没有右子树,当前节点是父节点的左节点。根据中序遍历的定义,下一个访问的节点就是父节点。这种情况也较简单。
  • 第二种(2):当前节点没有右子树,当前节点是父节点的右节点。这意味着父节点作为根节点的这棵树已经全部访问完了,需要去找到这样一个节点作为nextNode:以当前节点的父节点作为左子节点。 此时我们可以利用数据结构中的parent去往上追溯。追溯的过程中,如果追溯到了最顶端的根节点,这就说明整棵树都已经访问完了,不存在下一个访问的元素了。

代码

TreeNode结构代码

package q08;

/**
 * 二叉树的结构
 * @author asus
 *
 */
public class TreeNode {
	public int val;
	public TreeNode left;
	public TreeNode right;
	public TreeNode parent = null;
	public TreeNode(int x, TreeNode par) {
		this.val = x;
		this.parent = par;
	}
}

函数主体部分代码

package q08;

/**
 * 给定一颗二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?
 * 树中的节点除了有两个分别指向左右子节点的指针,还有一个指向父节点的指针。
 * @author asus
 *  */
public class Solution {
	public static TreeNode getNextNode(TreeNode node)
	{
		//若此节点为空,返回null
		if(node == null)
		{
			return null;
		}
		TreeNode nextNode = null;
		
		//node有右子树,则右子树中的最左节点就是nextNode
		if(node.right != null)
		{
			nextNode = node.right;
			//追踪至最左节点
			while(nextNode.left != null)
			{
				nextNode = nextNode.left;
			}
			return nextNode;
		}
		
		//node无右子树,且没有父节点,则不存在nextNode
		if(node.parent == null)
		{
			//这种情况node是根节点,且没有右子树,所以返回的是值为-1的节点
			nextNode = new TreeNode(-1, null);
			return nextNode;
		}
		//node无右子树,且是父节点的左子节点,则父节点就是nextNode
		if(node.parent.left == node)
		{
			nextNode = node.parent;
			return nextNode;
		}
		//node无右子树,且是父节点的右子节点,所以需要向上追溯到一个是父节点的左子节点的节点
		if(node.parent.right == node)
		{
			nextNode = node.parent;
			//若还没有追溯到此节点
			while(nextNode.parent != null && nextNode.parent.left != nextNode)
			{
				nextNode = nextNode.parent;
			}
			//出while有两种情况,一种是没有父节点了,一种是nextNode.parent.left == nextNode了
			//第一种情况,没有父节点了。
			if(nextNode.parent == null)
			{
				nextNode = new TreeNode(-1, null);
				return nextNode;
			}
			//第二种情况,父节点就是需要的nextNode
			nextNode = nextNode.parent;
			return nextNode;
		}
		return nextNode;
	}
}

测试部分代码

  • 我在测试部分创建了两个二叉树,对每个节点都进行了测验。

  • 第一个树是这样的,中序遍历序列是{4,6,8,10,12,14,16}
    在这里插入图片描述

  • 第二个树是这样的,中序遍历序列是{4,7,2,1,5,3,8,6}

package q08;

public class TestApp {

	public static void inorderOutput(TreeNode root)
	{
		if(root == null)
		{
			return;
		}
		inorderOutput(root.left);
		System.out.print(root.val + " ");
		inorderOutput(root.right);
	}
	
	public static void main(String[] args) {
		TreeNode root1 = new TreeNode(10, null);
		
		root1.left = new TreeNode(6, root1);
		root1.right = new TreeNode(14, root1);
		
		root1.left.left = new TreeNode(4, root1.left);
		root1.left.right = new TreeNode(8, root1.left);
		
		root1.right.left = new TreeNode(12, root1.right);
		root1.right.right = new TreeNode(16, root1.right);
		
		inorderOutput(root1);
		System.out.println();
		
		System.out.println("ROOT1: Node 10's next node in inorder is: " + Solution.getNextNode(root1).val);
		System.out.println("ROOT1: Node 6's next node in inorder is: " + Solution.getNextNode(root1.left).val);
		System.out.println("ROOT1: Node 14's next node in inorder is: " + Solution.getNextNode(root1.right).val);
		System.out.println("ROOT1: Node 4's next node in inorder is: " + Solution.getNextNode(root1.left.left).val);
		System.out.println("ROOT1: Node 8's next node in inorder is: " + Solution.getNextNode(root1.left.right).val);
		System.out.println("ROOT1: Node 12's next node in inorder is: " + Solution.getNextNode(root1.right.left).val);
		System.out.println("ROOT1: Node 16's next node in inorder is: " + Solution.getNextNode(root1.right.right).val);
		
		System.out.println();
		
		TreeNode root2 = new TreeNode(1, null);
		
		root2.left = new TreeNode(2, root2);
		root2.right = new TreeNode(3, root2);
		
		root2.left.left = new TreeNode(4, root2.left);
		
		root2.right.left = new TreeNode(5, root2.right);
		root2.right.right = new TreeNode(6, root2.right);
		
		root2.left.left.right = new TreeNode(7, root2.left.left);
		
		root2.right.right.left = new TreeNode(8, root2.right.right);
		
		inorderOutput(root2);
		System.out.println();
		
		System.out.println("ROOT2: Node 1's next node in inorder is: " + Solution.getNextNode(root2).val);
		System.out.println("ROOT2: Node 2's next node in inorder is: " + Solution.getNextNode(root2.left).val);
		System.out.println("ROOT2: Node 3's next node in inorder is: " + Solution.getNextNode(root2.right).val);
		System.out.println("ROOT2: Node 4's next node in inorder is: " + Solution.getNextNode(root2.left.left).val);
		System.out.println("ROOT2: Node 5's next node in inorder is: " + Solution.getNextNode(root2.right.left).val);
		System.out.println("ROOT2: Node 6's next node in inorder is: " + Solution.getNextNode(root2.right.right).val);
		System.out.println("ROOT2: Node 7's next node in inorder is: " + Solution.getNextNode(root2.left.left.right).val);
		System.out.println("ROOT2: Node 8's next node in inorder is: " + Solution.getNextNode(root2.right.right.left).val);
		
	}
}

运行结果截图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>