二叉树的下一个结点

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

思路:通过多次画图可以总结出来普遍的数学规律。假如我们要找结点b的中序遍历的下一个结点。根据中序遍历的特点,先访问b的左子树,然后访问结点b,最后访问b的右子树。
我们可以发现问题的关键在于b是否有右子树。
如上图所示:
1、如果结点b有右子树。那么结点b的下一个结点一定出现在其右子树的部分。具体在右子树的最左子树的那个结点。也就是m结点。
2、如果结点b无右子树。那么结点b的下一个结点会出现在回溯的路上。具体来说

  • 2.1 如果结点b是父亲结点的左孩子,那么b的下一个结点就是其父亲结点。也就是a
  • 2.2 如果结点b是父亲结点的右孩子,那么b的下一个结点应该是结点r。结点r是从b的父亲结点开始向上回溯,一旦出现左分支,就发现r了。

代码如下

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        if(pNode == NULL){
            return NULL;
        }
        //
        if(pNode->right != NULL){
            //有 右子树,那么下一个结点就是右子树的最左子树
            return FindLChild(pNode->right);
        }else{
            //没有 右子树
            if(pNode->next == NULL){
                return NULL;
            }else{
                if(pNode->next->left == pNode){
                    //左子树,返回父亲结点即可
                    return pNode->next;
                }else{
                    return FindRL_root(pNode->next);
                }
            }
        }
    }
    TreeLinkNode* FindRL_root(TreeLinkNode* node){
        if(node == NULL){
            return NULL;
        }
        TreeLinkNode* father =  node->next;
        while(father!=NULL){
            if(father->right == node){
                //继续循环
                node = father;
                father = father->next;
            }else if(father->left == node){
                return father;
            }
        }
        return father;

    }
    TreeLinkNode* FindLChild(TreeLinkNode* node){
        //找到该结点的最左子树,如果没有返回其本身即可
        while(node->left != NULL){
            node = node->left;
        }
        return node;
    }
};
posted @ 2021-03-11 12:56  focusDing  阅读(59)  评论(0编辑  收藏  举报