求二叉树中两个节点的最近公共祖先

来源:互联网 发布:英雄杀探宝数据 编辑:程序博客网 时间:2024/05/16 11:40

这里写图片描述
比如:在如图这棵二叉树中,8和9的公共祖先是1,4和5的公共祖先是2,5和2的公共祖先是2。

在上述分析中,我们可以得出思路,本题解法可分为两种情况,(1)两个节点在根节点同侧 ,则它们的最近公共祖先可能是其中一个节点,也可能是在到两个节点的公共路径上。
(2)两个节点在根节点的不同侧,则它们的公共祖先只能是根节点。

同时,这棵树又分为三种情况:
(1)这棵树是搜索树
(2)这棵树中有三叉链
(3)它只是一棵普通的二叉树

template<class T>struct BinaryTreeNode{    T _data;    BinaryTreeNode<T>* _left;    BinaryTreeNode<T>* _right;    BinaryTreeNode(const T& x)        :_data(x)        , _left(NULL)        , _parent(NULL)        , _right(NULL)       {}};

1,这棵树是搜索树:根据搜索树的性质,它的所有左子树小于根节点,所有右子树大于根节点。
时间复杂度O(N)

Node* GetCommonAncestor(Node* root,Node* x1, Node* x2)    {        if (root == NULL)            return NULL;        else if ((x1->_data >= root->_data && x2->_data <= root->_data)            || (x1->_data <= root->_data && x2->_data >= root->_data))            return root;        else if (x1->_data < root->_data && x2->_data < root->_data)            GetCommonAncestor(root->_left, x1, x2);        else if (x1->_data > root->_data && x2->_data > root->_data)            GetCommonAncestor(root->_right, x1, x2);    }

2,普通二叉树
时间复杂度O(N^2)

Node* GetCommonAncesstor(Node* root, Node* x1,Node*x2)    {        if (root == NULL)            return NULL;        if (x1 == NULL || x2 == NULL)            return NULL;        else        {            bool X1Inleft, X1Inright, X2Inleft, X2Inright;            X1Inleft = GetCommonAncesstor(root->_left, x1);            X1Inright = GetCommonAncesstor(root->_right, x1);            assert(X1Inleft || X1Inright);            X2Inleft = GetCommonAncesstor(root->_left, x1);            X2Inright = GetCommonAncesstor(root->_right, x2);            assert(X2Inleft || X2Inright);            if (X1Inleft&&X2Inleft)                return GetCommonAncesstor(root->_left, x1, x2);            if (X1Inright&&X2Inright)                return GetCommonAncesstor(root->_right, x1, x2);            else                return root;        }    }

优化为O(N)

Node* GetNodePath(Node* root,stack<Node*>& s, Node* x)    {        if (root)            s.push(root);        if (root->_data == x1->_data)            return true;        bool left = GetNodePath(root->_left, s, x);        if (left)            return true;        bool right = GetNodePath(root->_right, s, x);        if (right);        return true;        s.pop();        return false;    }    Node* GetNodeAncestor(Node* root, Node* x1, Node* x2)    {        if (NULL == root)            return NULL;        assert(x1 && x2);        stack<Node*> s1, s2;        if (!GetNodePaths(root, s1, x1) || !GetNodePaths(root, s2, x2))            return NULL;        while (s1.size() != s2.size())        {            if (s1.size() > s2.size())                s1.pop();            if (s1.size() < s2.size())                s2.pop();        }        while (!s1.empty() && !s2.empty() && s1.top() != s2.top())            {                    s1.pop();                    s2.pop();            }        return s1.top();        }

3,这棵二叉树中有三叉链

template<class T>struct BinaryTreeNode{    T _data;    BinaryTreeNode<T>* _left;    BinaryTreeNode<T>* _right;    BinaryTreeNode<T>* _parent;    BinaryTreeNode(const T& x)        :_data(x)        , _left(NULL)        , _parent(NULL)        , _right(NULL)       {}};
Node* GetCommenAncesstor(Node* root, Node* x1, Node* x2)    {        stack<Node*> s1;        stack<Node*> s2;        Node* cur1 = x1;        Node* cur2 = x2;        while (cur1->_parent)        {            if (cur1->_parent->_data == cur2->_data)                return cur;            else                s1.push(cur1);            cur1 = cur1->_parent;        }        while (cur2->_parent)        {            if (cur2->_parent->_data == cur1->_data)                return cur1;            else                s2.push(cur2);            cur2 = cur2->_parent;        }        Node* node = NULL;        while (!s1.empty() && !s2.empty())        {            if (s1.pop() == s2.pop())                node = s1.pop();            else                return node;            s1.pop();            s2.pop();        }        return node;    }
阅读全文
1 0
原创粉丝点击