zoukankan      html  css  js  c++  java
  • 08 二叉树的下一个节点

    题目描述:

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

    测试用例:

     1)普通二叉树(完全二叉树、不完全二叉树)

     2)特殊二叉树(所有节点都没有右/左子节点的二叉树,只有一个节点的二叉树,空树:根节点指针为nullptr)

     3)不同位置的节点的下一个节点(下一个节点为当前节点的右子节点、右子树的最左节点、父节点、跨层的父节点;当前节点没有下一个节点)

    解题思路:

     建议:在解题时,画出具体的二叉树结构图、通过具体的例子找出中序遍历下一个节点的规律,设计可行的方法。

    分三种情况讨论:

     1)如果一个节点有右子树,那么它的下一个节点就是它的右子树的最左节点。即从右子节点出发一直沿着左子节点的指针寻找。如图中b(h)与a(f)。

     2)该节点没有右子树,且该节点是其父节点的左节点,下一个节点是它的父节点。

     3)该节点没有右子树,且该节点是其父节点的右节点时:可以沿着指向父节点的指针一直向上遍历,直到找到一个是它父节点的左子节点的节点。如果这样的节点存在,那么这个节点的父节点就是要找的下一个节点

     4)初始化要找的下一个节点时,设为空指针。没有找到时,直接返回该空指针。

    代码:

     1)

    /*
    struct TreeLinkNode {
        int val;
        struct TreeLinkNode *left;  //此处的struct对调用有影响么?没有
        struct TreeLinkNode *right;
        struct TreeLinkNode *next;
        TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
            
        }
    };
    */
    class Solution {
    public:
        //pNode: 给定的节点 不要修改其值
        TreeLinkNode* GetNext(TreeLinkNode* pNode)
        {
             if( pNode == NULL ) //nullptr
                 return NULL;
             //TreeLinkNode* nextNode = NULL ;
             TreeLinkNode* nextNode = nullptr ;
             //TreeLinkNode* nextNode = new TreeLinkNode();
             if (pNode->right != NULL){
                 //error : 右子树非空,右子树的root节点则是指定节点pNode中序的下一个节点。
                 //nextNode = pNode->right;
                 //右子树非空,右子树的最左节点则是指定节点pNode中序的下一个节点。
                 TreeLinkNode* rightTree = pNode->right ;
                 while(rightTree->left!=NULL){
                     rightTree = rightTree->left ;
                 }
                 //把找到的左节点赋给返回值
                 nextNode = rightTree;
             }else if (pNode->next!= nullptr){ //父节点非空--根节点没有父节点
                 //右子树为空时,根据父节点判断指定节点pNode是左子树还是右子树
                 if(pNode == pNode->next->left){
                     //是左节点,则在中序遍历中父节点是该节点的下一个节点
                     nextNode = pNode->next ;
                 }else{
                     //是右节点
                     //父节点是左节点,取父节点的父节点。父节点是右节点,对父节点的父节点重新判断。。。
                     //一直找到父节点是左节点的节点。
                     TreeLinkNode* parantNode = pNode->next ;
                     TreeLinkNode* currentNode = pNode ;
                     while(parantNode!=nullptr && currentNode == parantNode->right){
                         currentNode = parantNode;
                         parantNode = parantNode->next ;
                     }
                     nextNode = currentNode->next ;
                 }
                 
             }
              return nextNode;
        }
    };  

     注意:

    「1」注意中英文字符

    「2」line22-28,当右子树非空时,下一个节点应该时右子树的最左节点,而不是根节点。

    「3」line32一定要判断父节点非空才可以使用父节点 ->next,因为并不是所有的节点都有父节点,如树的根节点

    「4」在程序运行中,不要修改输入参数pNode,创建新的变量。如 currentNode 、parantNode 等。

     2)思路同上面是一致的,只是在第三种情况时,代码更简洁。

    /*
    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 == nullptr){
                return nullptr;
            }
            TreeLinkNode* next = nullptr;
            //先右子节点的左子节点遍历
            if(pNode->right != nullptr){
                TreeLinkNode* rightNode  = pNode->right;
                while(rightNode->left != nullptr){
                    rightNode = rightNode->left;
                }
                next = rightNode;
            }
                //向父结点遍历
            else if(pNode->next != nullptr){ //一定要判断父节点是否非空
                TreeLinkNode* parentNode = pNode->next;
                TreeLinkNode* currentNode = pNode;
                //当前节点是左节点时,不进入while循环。右节点进入循环
                //一定要判断父节点是否非空
                while(parentNode != nullptr  && currentNode == parentNode->right){
                    currentNode = parentNode;
                    parentNode = parentNode->next;
                }
                next = parentNode;
            }
            return next;
        }
    };
    

    基础知识:

     [1] NULL是0,nullptr是空指针void

    https://blog.csdn.net/jays_/article/details/82586699 

     [2] 对变量的命名,要有意义。如父节点 parentNode,不要随便写pp、pc这种名字。

  • 相关阅读:
    _ 下划线 Underscores __init__
    Page not found (404) 不被Django的exception中间件捕捉 中间件
    从装修儿童房时的门锁说起
    欧拉定理 费马小定理的推广
    线性运算 非线性运算
    Optimistic concurrency control 死锁 悲观锁 乐观锁 自旋锁
    Avoiding Full Table Scans
    批量的单向的ssh 认证
    批量的单向的ssh 认证
    Corrupted MAC on input at /usr/local/perl/lib/site_perl/5.22.1/x86_64-linux/Net/SSH/Perl/Packet.pm l
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10400544.html
Copyright © 2011-2022 走看看