二叉树的下一个节点——C++

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

根据剑指offer,进行了梳理:

总共分为三种情况:
1、若一个节点有右子树,则下一个节点为它的右子树的最左子节点。即从右子节点处出发一直沿着指向左子节点的指针,就可以找到它的下一个节点。如C的下一个节点是B,E的下一个节点是M。

2、一个节点没有右子树,但它是它的父节点的左子树,则下一个节点就是它的父节点,如A的下一个节点是C,M的下一个节点是G,H的下一个节点是E

3、一个节点没有右子树,且它是它的父节点的右子树,则沿父节点指针一路向上,直到找到一个这样一个节点:这个节点是这个节点的父节点的左子树。则该节点的父节点就是要找的下一个节点。如D的父节点为C,C是C的父节点F的左子树,故F是要找的下一个节点。

又比如G的父节点是E,E是E的父节点F的右子树,不符合条件,继续向上遍历找到F,由于F是根节点,故F节点没有父节点,因此节点G没有下一个节点。

按照上述思路,我自己进行了编程(但是有点尴尬的是,因为我看的书是剑指offer,书中提到的是二叉树的下一个节点,但是leetcode上缺了这道题,我找到了类似的题目,但leetcode给出的是搜索二叉树的下一个节点,我写完整个题目看官解时才发现,这里我给出的代码是针对所有二叉树的,在leetcode中也能通过,就是少了搜索二叉树的性质,写起来多了很多麻烦):

由于leetcode的题(面试题 04.06. 后继者)中并没有像剑指offer(面试题8)一样给出父节点,故首先利用哈希结构遍历一遍整棵树,并记录存储每个子节点的父节点

    void InitMap(TreeNode* root)
    {
        if(root ==nullptr)
        return;

        if(root->left)
        {
           InitMap(root->left);
           TMap[root->left]=root;
        }
        if(root->right)
        {
           InitMap(root->right);
           TMap[root->right]=root;
        }
    }

随后,便可以按照上面所述的三种情况进行讨论,具体代码如下

   TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if(!p)
        return nullptr;

        TMap[root]=nullptr;
        InitMap(root);                       //形成子节点与父节点对应的Map
        if(p->right)                         //若有右子树,则下一个节点为 右子树的最左子节点
        {
            TreeNode* Temp = p->right;
            while(Temp->left)
                Temp = Temp->left;
            return Temp;
        }
        else if(!p->right && TMap[p] && TMap[p]->left==p)  
            return TMap[p];                        //没有右子树,但是该节点是父节点的左子树 
        else                                       //没有右子树,并且该节点是父节点的右子树
        {
            TreeNode* Temp = TMap[p];
            while(Temp!= nullptr && TMap[Temp]!=nullptr && TMap[Temp]->left !=Temp )
                Temp = TMap[Temp];
            
            if( TMap[Temp]!=nullptr && TMap[Temp]->left == Temp)
               return TMap[Temp];
            else 
               return nullptr;
        }
        return nullptr;
       
    }

官解利用了中序遍历的性质,具体如下:

为了找到二叉搜索树中的节点 p 的后继节点,最直观的方法是中序遍历。由于只需要找到节点 p 的后继节点,因此不需要维护完整的中序遍历序列,只需要在中序遍历的过程中维护上一个访问的节点和当前访问的节点。如果上一个访问的节点是节点 p,则当前访问的节点即为节点 p 的后继节点。如果节点 p是最后被访问的节点,则不存在节点 p 的后继节点,返回 null。

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        stack<TreeNode*> st;
        TreeNode *prev = nullptr, *curr = root;
        while (!st.empty() || curr != nullptr) {
            while (curr != nullptr) {
                st.emplace(curr);
                curr = curr->left;
            }
            curr = st.top();
            st.pop();
            if (prev == p) {
                return curr;
            }
            prev = curr;
            curr = curr->right;
        }
        return nullptr;
    }
};

下面一段是官方按照我上述的思路给出的题解,代码比我写的简短很多,主要是其用到了搜索二叉树的性质。

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        TreeNode *successor = nullptr;
        if (p->right != nullptr) {
            successor = p->right;
            while (successor->left != nullptr) {
                successor = successor->left;
            }
            return successor;
        }
        TreeNode *node = root;
        while (node != nullptr) {
            if (node->val > p->val) {
                successor = node;
                node = node->left;
            } else {
                node = node->right;
            }
        }
        return successor;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值