Day57:二叉树的下一个结点

时间:2022-07-24
本文章向大家介绍Day57:二叉树的下一个结点,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

剑指Offer_编程题——二叉树的下一个结点

题目描述:

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

具体要求:

时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M

具体实现:

思路一:   在做题前,我们应该给大家介绍二叉树的中序遍历的相关知识:在前面的文章里给大家介绍过二叉树的遍历。因此,这里就给大家不详细介绍了。现在给大家介绍解题思路:我们根据对二叉树知识的了解,可以将情况分为三种:第一种:有右孩子,找到右孩子,循环遍历右孩子的左节点、第二种:没有右孩子,而且是根的左孩子,返回父亲节点、第三种:是父亲节点的右孩子,而且没有右孩子,则返回父亲节点的父节点等。具体的过程如下图所示:

因此,我们可以使用java来实现该思路:

public class Solution{
	public TreeLinkNode GetNext(TreeLinkNode pNode){
		if(pNode.right != null){
			pNode = pNode.right;
			while(pNode.left != null){
				pNode = pNode.left;
			}
				return pNode;
		}
		while(pNode.next != null && pNode.next.right == pNode){
			pNode = pNode.next;
		}
		return pNode.next;
	}
}

代码效果图如图所示:

  正如前面说的那样,如果在牛客网中,我们可以直接通过,但是如果是本地的编译器,则还需要定义其结点,具体结点的实现定义用java实现如下:

public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;
    TreeLinkNode(int val) {
        this.val = val;
    }
}

思路二:   根据前面对中序遍历的介绍,如果一个节点的右子树不为空,那么该节点的下一个节点是右子树的最左节点;那么需要首先判断给定的结点属于哪一种:如果它存在右子树,说明它是子树的父结点,下一个节点在其右子树中。如果右子树存在左孩子结点,那么下一个就是左孩子结点,否则说明它就是叶子结点,直接返回。如果它不存在右子树,说明当前结点为叶子节点:如果当前结点为右叶子,那么下一个就是它的父结点,即它next域指向的结点。如果它的父节点有左叶子,说明下一个节点就是父节点

② 否则,向上找第一个左链接指向的树包含该节点的祖先节点。

  接下来我们分别用java和python两种语言来实现该思路: 1、首先我们用java实现该思路:

public class Solution{
	public TreeLinkNode GetNext(TreeLinkNode pNode){
		if(pNode.right != null){
			TreeLinkNode node = pNode.right;
			while(node.left != null){
				node = node.left;
			}
			return node;
		}else{
			while(pNode.next !=null){
				TreeLinkNode parent = pNode.next;
				if(parent.left == pNode){
					return parent;
				}
				pNode = pNode.next;
			}
		}
		return null;
	}
}

代码效果图如图所示:

2、接下来我们用Python将其实现:

class Solution:
	def GetNext(self, pNode):
		if pNode == None:
			return None
		if pNode.right:
			pNode = pNode.right
			while pNode.left:
				pNode = pNode.left
			return pNode
		else:
			while pNode.next:
				if pNode == pNode.next.left:
					return pNode.next
				pNode = pNode.next
		return None

代码效果图如图所示:

  但是在本地编译器中我们还需要定义链表结构才能正常运行,具体用python定义链表结构实现如下:

class TreeLinkNode:
	def __init__(self, pNode):
		self.val = x
		self.left = None
		self.right = None
		self.next = None

思路三:   无论是何种思路,首先要做的就是要知道二叉树的中序遍历。具体如下:

  结合上图,我们可发现分成两大类: 1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) 2、没有右子树的,也可以分成两类:(a)是父节点左孩子(eg:N,I,L) ,那么父节点就是下一个节点 ;b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点…直到当前结点是其父节点的左孩子位置。如果没有eg:M,那么他就是尾节点。)。   具体我们用python将其实现:

class Solution:
	def GetNext(self, pNode):
		if not pNode:
			return pNode
		if pNode.right:
			left1 = pNode.right
			while left1.left:
				left1 = left1.left
			return left1
		p = pNode
		while pNode.next:
			tmp = pNode.next
			if tmp.left == pNode:
				return tmp
			pNode = tmp

代码效果图如图所示:

总结

  本题主要通过二叉树的中序遍历来考察我们对二叉树遍历的应用,我们不仅要掌握二叉树的遍历,更要掌握其在不同的应用。本文给出了三种解题方法,并且这三种方法其实都是以中序遍历为依托的。另外我们还通过java和python将其实现。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1] jiangjiane [2] Forlogen [3] DrogoZhang [4] 白马长枪儒雅将