• 《剑指offer》第八题:二叉树的下一个节点


    // 面试题8:二叉树的下一个结点
    // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?
    // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针。
    
    #include <stdio.h>
    
    struct BinaryTreeNode
    {
        int             m_nValue;
        BinaryTreeNode* m_pLeft;
        BinaryTreeNode* m_pRight;
        BinaryTreeNode* m_pParent;
    };
    
    BinaryTreeNode* GetNext(BinaryTreeNode* pNode)
    {
        //鲁棒性测试 1.空指针
        if (pNode == nullptr)
            return nullptr;
    
        BinaryTreeNode* pNext = nullptr;
        //如果该父节点有右子树,返回右子树的左子节点
        if (pNode->m_pRight != nullptr)
        {
            BinaryTreeNode* pRight = pNode->m_pRight;
            while (pRight->m_pLeft != nullptr)
            {
                pRight = pRight->m_pLeft;
            }
            pNext = pRight;
        }
        //如果无右节点, 分两种情况
        else if (pNode->m_pParent != nullptr) //检查父节点
        {
            BinaryTreeNode* pCurrent = pNode;
            BinaryTreeNode* pParent = pNode->m_pParent;
            //如果节点为父节点的右子节点, 则向上遍历寻找是其父节点左子节点的节点
            while (pParent != nullptr && pParent->m_pRight == pCurrent) //注意判断顺序,读取访问权限冲突 
            //while (pParent->m_pRight == pCurrent && pParent != nullptr)
            {
                pCurrent = pParent;
                pParent = pParent->m_pParent;
            }
            //如果为父节点的左子节点, 返回父节点
            pNext = pParent;
        }
        return pNext;
    }
    // ==================== 辅助代码用来构建二叉树 ====================
    BinaryTreeNode* CreateBinaryTreeNode(int value)
    {
        BinaryTreeNode* pNode = new BinaryTreeNode();
        pNode->m_nValue = value;
        pNode->m_pLeft = nullptr;
        pNode->m_pRight = nullptr;
        pNode->m_pParent = nullptr;
    
        return pNode;
    }
    
    void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
    {
        if (pParent != nullptr)
        {
            pParent->m_pLeft = pLeft;
            pParent->m_pRight = pRight;
    
            if (pLeft != nullptr)
                pLeft->m_pParent = pParent;
            if (pRight != nullptr)
                pRight->m_pParent = pParent;
        }
    }
    
    void PrintTreeNode(BinaryTreeNode* pNode)
    {
        if (pNode != nullptr)
        {
            printf("value of this node is: %d
    ", pNode->m_nValue);
    
            if (pNode->m_pLeft != nullptr)
                printf("value of its left child is: %d.
    ", pNode->m_pLeft->m_nValue);
            else
                printf("left child is null.
    ");
    
            if (pNode->m_pRight != nullptr)
                printf("value of its right child is: %d.
    ", pNode->m_pRight->m_nValue);
            else
                printf("right child is null.
    ");
        }
        else
        {
            printf("this node is null.
    ");
        }
    
        printf("
    ");
    }
    
    void PrintTree(BinaryTreeNode* pRoot)
    {
        PrintTreeNode(pRoot);
    
        if (pRoot != nullptr)
        {
            if (pRoot->m_pLeft != nullptr)
                PrintTree(pRoot->m_pLeft);
    
            if (pRoot->m_pRight != nullptr)
                PrintTree(pRoot->m_pRight);
        }
    }
    
    void DestroyTree(BinaryTreeNode* pRoot)
    {
        if (pRoot != nullptr)
        {
            BinaryTreeNode* pLeft = pRoot->m_pLeft;
            BinaryTreeNode* pRight = pRoot->m_pRight;
    
            delete pRoot;
            pRoot = nullptr;
    
            DestroyTree(pLeft);
            DestroyTree(pRight);
        }
    }
    辅助代码
    // ====================测试代码====================
    void Test(const char* testName, BinaryTreeNode* pNode, BinaryTreeNode* expected)
    {
        if (testName != nullptr)
            printf("%s begins: ", testName);
    
        BinaryTreeNode* pNext = GetNext(pNode);
        if (pNext == expected)
            printf("Passed.
    ");
        else
            printf("FAILED.
    ");
    }
    
    //            8
    //        6      10
    //       5 7    9  11
    void Test1_7()
    {
        BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
        BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
        BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
        BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
        BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
        BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
        BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
    
        ConnectTreeNodes(pNode8, pNode6, pNode10);
        ConnectTreeNodes(pNode6, pNode5, pNode7);
        ConnectTreeNodes(pNode10, pNode9, pNode11);
    
        Test("Test1", pNode8, pNode9);
        Test("Test2", pNode6, pNode7);
        Test("Test3", pNode10, pNode11);
        Test("Test4", pNode5, pNode6);
        Test("Test5", pNode7, pNode8);
        Test("Test6", pNode9, pNode10);
        Test("Test7", pNode11, nullptr);
    
        DestroyTree(pNode8);
    }
    
    //            5
    //          4
    //        3
    //      2
    void Test8_11()
    {
        BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
        BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
        BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
        BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
    
        ConnectTreeNodes(pNode5, pNode4, nullptr);
        ConnectTreeNodes(pNode4, pNode3, nullptr);
        ConnectTreeNodes(pNode3, pNode2, nullptr);
    
        Test("Test8", pNode5, nullptr);
        Test("Test9", pNode4, pNode5);
        Test("Test10", pNode3, pNode4);
        Test("Test11", pNode2, pNode3);
    
        DestroyTree(pNode5);
    }
    
    //        2
    //         3
    //          4
    //           5
    void Test12_15()
    {
        BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
        BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
        BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
        BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
    
        ConnectTreeNodes(pNode2, nullptr, pNode3);
        ConnectTreeNodes(pNode3, nullptr, pNode4);
        ConnectTreeNodes(pNode4, nullptr, pNode5);
    
        Test("Test12", pNode5, nullptr);
        Test("Test13", pNode4, pNode5);
        Test("Test14", pNode3, pNode4);
        Test("Test15", pNode2, pNode3);
    
        DestroyTree(pNode2);
    }
    
    void Test16()
    {
        BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
    
        Test("Test16", pNode5, nullptr);
    
        DestroyTree(pNode5);
    }
    
    int main(int argc, char* argv[])
    {
        Test1_7();
        Test8_11();
        Test12_15();
        Test16();
    }
    测试代码

    分析:根据实例分析规律。注意不要出现读取访问冲突。

    /*
    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* pNext = nullptr;
            if (pNode->right != nullptr)
            {
                TreeLinkNode* pRight = pNode->right;
                while (pRight->left != nullptr)
                    pRight = pRight->left;
                
                pNext = pRight;
            }
            else if (pNode->next != nullptr)
            {
                TreeLinkNode* pCurrent = pNode;
                TreeLinkNode* pParent = pNode->next;
                while (pParent != nullptr && pCurrent == pParent->right)
                {
                    pCurrent = pParent;
                    pParent = pParent->next;
                }
                pNext = pParent;
            }
            return pNext;
        }
    };
    牛客网提交代码
  • 相关阅读:
    高德地图API1.4.15较1.4.12的marker属性取值发生变化
    Cesium加载地图提示RangeError:Invalid of array List
    layui分页功能使用——点页码再查询
    设置layui的自定义样式
    页面引入layui.js后提示layui未定义
    SQL语句出现sql关键字
    vs2017 vs2019配置sqlite3连接引擎(驱动)指南(二)vs2019续集
    vs2017 vs2019配置sqlite3连接引擎(驱动)指南(一)vs2019篇
    Qt C++ QDataStream和QBuffer
    Qt C++不规则窗口
  • 原文地址:https://www.cnblogs.com/ZSY-blog/p/12542998.html
Copyright © 2020-2023  润新知