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

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

牛客网:链接

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

上图二叉树的中序遍历是d,b,h,e,i,a,f,c,g。我们以这棵树为例来分析如何找出二叉树的下一个结点。

以是否有右子树为分界点。如果一个结点有右子树,那么它的下一个结点就是它的右子树的最左子结点。也就是说从右子结点出发一直沿着指向左子树结点的指针,我们就能找到它的下一个结点。例如,图中结点b的下一个结点是h,结点a的下一个结点是f。

接着我们分析一下结点没有右子树的情形。如果结点是它父结点的左子结点,那么它的下一个结点就是它的父结点。例如,途中结点d的下一个结点是b,f的下一个结点是c。

如果一个结点既没有右子树,并且它还是父结点的右子结点,这种情形就比较复杂。我们可以沿着指向父结点的指针一直向上遍历,直到找到一个是它父结点的左子结点的结点。如果这样的结点存在,那么这个结点的父结点就是我们要找的下一个结点。例如,为了找到结点g的下一个结点,我们沿着指向父结点的指针向上遍历,先到达结点c。由于结点c是父结点a的右结点,我们继续向上遍历到达结点a。由于结点a是树的根结点。它没有父结点。因此结点g没有下一个结点。

# -*- coding:utf-8 -*-
class TreeLinkNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
        self.next = None
        
class Solution:
    def GetNext(self, pNode):
        '''输入是一个空节点'''
        if pNode == None:
            return None
        '''注意当前节点是根节点的情况。所以在最开始设定pNext = None, 如果下列情况都不满足, 说明当前结点为根节点, 直接输出None'''
        pNext = None
        '''如果输入节点有右子树,则下一个结点是当前节点右子树中最左节点'''
        if pNode.right:
            pNode = pNode.right
            while pNode.left:
                pNode = pNode.left
            pNext = pNode
        else:
            '''如果当前节点有父节点且当前节点是父节点的左子节点, 下一个结点即为父节点'''
            '''如果当前节点有父节点且当前节点是父节点的右子节点, 那么向上遍历
               当遍历到当前节点为父节点的左子节点时, 输入节点的下一个结点为当前节点的父节点'''
            if pNode.next and pNode.next.left == pNode:
                pNext = pNode.next
            elif pNode.next and pNode.next.right == pNode:
                pNode = pNode.next
                while pNode.next and pNode.next.left != pNode:
                    pNode = pNode.next
                '''遍历终止时当前节点有父节点, 说明当前节点是父节点的左子节点, 输入节点的下一个结点为当前节点的父节点'''
                '''反之终止时当前节点没有父节点, 说明当前节点在位于根节点的右子树, 没有下一个结点'''
                if pNode.next:
                    pNext = pNode.next
        return pNext