【剑指offer】8 - 二叉树的下一个节点

题目描述
  • 题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针
  • 二叉树节点结构:
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *parent;
    TreeLinkNode(int x) 
        :val(x), left(NULL), right(NULL), parent(NULL) 
    {}
};
解题思路
  • 为了方便分析,我们以下面这颗二叉树为例:
    二叉树
  • 此树的中序遍历结果为:d -> b -> h -> e -> i -> a -> f -> c -> g
  • 我们按照中序遍历分情况进行讨论:
  • 第一种:该节点有右子树,则根据中序遍历序列,下一个节点是该节点右子树的最左子树,举例说明:b 节点的下一个节点是 h;c 节点的下一个节点是 g
  • 第二种:该节点没有右子树,按照中序遍历序列,此时我们应该向追溯到上一层,此时就可以再次分情况了:
    • 第一种:该节点是其父节点的左孩子,则下一个节点即为该节点的父节点,举例说明:h 节点的下一个节点是它的父节点 e
    • 第二种:该节点是其父节点的右孩子,则这个节点一定是某颗子树中序遍历的最后一个节点,那么下一个节点即为这颗子树根节点的父节点。我们需要做的是找出这颗子树,并且这棵树一定是包含该节点但是不包含根节点(否则该节点的下一个节点为空)的最上层子树。所以此时我们需要做的是沿着指向父节点的指针向上遍历,直到找到是它父节点的左子节点的节点,以该节点为根的子树就是我们要找的,此时下一个节点即为该节点的父节点。举例说明:i 节点的下一个节点,我们需要通过指向父节点的指针一直向上找到 b 节点,此时 i 节点的下一个节点即为 b 节点的父节点
  • 思路理清楚后,我们就可以开始写代码了
代码实现
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
    if(pNode == NULL)
        return NULL;
    TreeLinkNode* pNext = NULL;
    //1.该节点有右子树
    if(pNode->right != NULL)
    {
        //找其右子树的最左节点
        TreeLinkNode* pRight = pNode->right;
        while(pRight->left != NULL)
            pRight = pRight->left;
        pNext = pRight;
    }
    //2.若该节点无右子树,我们要追溯到其父节点这一层进行进一步判断
    else if(pNode->parent != NULL)
    {
        TreeLinkNode* pCur = pNode;
        TreeLinkNode* pParent = pNode->parent;
        //第二种情况的主要思想就是找到包含该节点的最大子树(不包含根节点),并且该子树是其父节点的左子树
        while(pParent != NULL && pCur == pParent->right)
        {
            pCur = pParent;
            pParent = pParent->parent;
        }
        pNext = pParent;
    }
    return pNext;
}

猜你喜欢

转载自blog.csdn.net/Aurora_pole/article/details/81623643