树中两个结点的最低公共祖先-C++

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程icon-default.png?t=N7T8https://www.captainai.net/

// 面试题68:树中两个结点的最低公共祖先
// 题目:输入两个树结点,求它们的最低公共祖先。

#include <cstdio>
#include <list>
#include <vector>

using namespace std;

struct TreeNode
{
    int m_nValue;
    std::vector<TreeNode *> m_vChildren;
};

TreeNode *CreateTreeNode(int value)
{
    TreeNode *pNode = new TreeNode();
    pNode->m_nValue = value;

    return pNode;
}

void ConnectTreeNodes(TreeNode *pParent, TreeNode *pChild)
{
    if (pParent != nullptr)
    {
        pParent->m_vChildren.push_back(pChild);
    }
}

void PrintTreeNode(const TreeNode *pNode)
{
    if (pNode != nullptr)
    {
        printf("value of this node is: %d.\n", pNode->m_nValue);

        printf("its children is as the following:\n");
        std::vector<TreeNode *>::const_iterator i = pNode->m_vChildren.begin();
        while (i < pNode->m_vChildren.end())
        {
            if (*i != nullptr)
                printf("%d\t", (*i)->m_nValue);
        }

        printf("\n");
    }
    else
    {
        printf("this node is nullptr.\n");
    }

    printf("\n");
}

void PrintTree(const TreeNode *pRoot)
{
    PrintTreeNode(pRoot);

    if (pRoot != nullptr)
    {
        std::vector<TreeNode *>::const_iterator i = pRoot->m_vChildren.begin();
        while (i < pRoot->m_vChildren.end())
        {
            PrintTree(*i);
            ++i;
        }
    }
}

void DestroyTree(TreeNode *pRoot)
{
    if (pRoot != nullptr)
    {
        std::vector<TreeNode *>::iterator i = pRoot->m_vChildren.begin();
        while (i < pRoot->m_vChildren.end())
        {
            DestroyTree(*i);
            ++i;
        }

        delete pRoot;
    }
}

bool GetNodePath(const TreeNode *pRoot, const TreeNode *pNode, list<const TreeNode *> &path)
{
    if (pRoot == pNode)
        return true;

    path.push_back(pRoot);

    bool found = false;

    vector<TreeNode *>::const_iterator i = pRoot->m_vChildren.begin();
    while (!found && i < pRoot->m_vChildren.end())
    {
        found = GetNodePath(*i, pNode, path);
        ++i;
    }

    if (!found)
        path.pop_back();

    return found;
}

const TreeNode *GetLastCommonNode(
    const list<const TreeNode *> &path1,
    const list<const TreeNode *> &path2)
{
    list<const TreeNode *>::const_iterator iterator1 = path1.begin();
    list<const TreeNode *>::const_iterator iterator2 = path2.begin();

    const TreeNode *pLast = nullptr;

    while (iterator1 != path1.end() && iterator2 != path2.end())
    {
        if (*iterator1 == *iterator2)
            pLast = *iterator1;

        iterator1++;
        iterator2++;
    }

    return pLast;
}

const TreeNode *GetLastCommonParent(const TreeNode *pRoot, const TreeNode *pNode1, const TreeNode *pNode2)
{
    if (pRoot == nullptr || pNode1 == nullptr || pNode2 == nullptr)
        return nullptr;

    list<const TreeNode *> path1;
    GetNodePath(pRoot, pNode1, path1);

    list<const TreeNode *> path2;
    GetNodePath(pRoot, pNode2, path2);

    return GetLastCommonNode(path1, path2);
}

// ====================测试代码====================
void Test(const char *testName, const TreeNode *pRoot, const TreeNode *pNode1, const TreeNode *pNode2, TreeNode *pExpected)
{
    if (testName != nullptr)
        printf("%s begins: ", testName);

    const TreeNode *pResult = GetLastCommonParent(pRoot, pNode1, pNode2);

    if ((pExpected == nullptr && pResult == nullptr) ||
        (pExpected != nullptr && pResult != nullptr && pResult->m_nValue == pExpected->m_nValue))
        printf("Passed.\n");
    else
        printf("Failed.\n");
}

// 形状普通的树
//              1
//            /   \
//           2     3
//       /       \
//      4         5
//     / \      / |  \
//    6   7    8  9  10
void Test1()
{
    TreeNode *pNode1 = CreateTreeNode(1);
    TreeNode *pNode2 = CreateTreeNode(2);
    TreeNode *pNode3 = CreateTreeNode(3);
    TreeNode *pNode4 = CreateTreeNode(4);
    TreeNode *pNode5 = CreateTreeNode(5);
    TreeNode *pNode6 = CreateTreeNode(6);
    TreeNode *pNode7 = CreateTreeNode(7);
    TreeNode *pNode8 = CreateTreeNode(8);
    TreeNode *pNode9 = CreateTreeNode(9);
    TreeNode *pNode10 = CreateTreeNode(10);

    ConnectTreeNodes(pNode1, pNode2);
    ConnectTreeNodes(pNode1, pNode3);

    ConnectTreeNodes(pNode2, pNode4);
    ConnectTreeNodes(pNode2, pNode5);

    ConnectTreeNodes(pNode4, pNode6);
    ConnectTreeNodes(pNode4, pNode7);

    ConnectTreeNodes(pNode5, pNode8);
    ConnectTreeNodes(pNode5, pNode9);
    ConnectTreeNodes(pNode5, pNode10);

    Test("Test1", pNode1, pNode6, pNode8, pNode2);
}

// 树退化成一个链表
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test2()
{
    TreeNode *pNode1 = CreateTreeNode(1);
    TreeNode *pNode2 = CreateTreeNode(2);
    TreeNode *pNode3 = CreateTreeNode(3);
    TreeNode *pNode4 = CreateTreeNode(4);
    TreeNode *pNode5 = CreateTreeNode(5);

    ConnectTreeNodes(pNode1, pNode2);
    ConnectTreeNodes(pNode2, pNode3);
    ConnectTreeNodes(pNode3, pNode4);
    ConnectTreeNodes(pNode4, pNode5);

    Test("Test2", pNode1, pNode5, pNode4, pNode3);
}

// 树退化成一个链表,一个结点不在树中
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test3()
{
    TreeNode *pNode1 = CreateTreeNode(1);
    TreeNode *pNode2 = CreateTreeNode(2);
    TreeNode *pNode3 = CreateTreeNode(3);
    TreeNode *pNode4 = CreateTreeNode(4);
    TreeNode *pNode5 = CreateTreeNode(5);

    ConnectTreeNodes(pNode1, pNode2);
    ConnectTreeNodes(pNode2, pNode3);
    ConnectTreeNodes(pNode3, pNode4);
    ConnectTreeNodes(pNode4, pNode5);

    TreeNode *pNode6 = CreateTreeNode(6);

    Test("Test3", pNode1, pNode5, pNode6, nullptr);
}

// 输入nullptr
void Test4()
{
    Test("Test4", nullptr, nullptr, nullptr, nullptr);
}

int main(int argc, char *argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();

    return 0;
}

// ------ Output ------
/*
Test1 begins: Passed.
Test2 begins: Passed.
Test3 begins: Passed.
Test4 begins: Passed.
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值