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

来源:互联网 发布:淘宝提交订单不付款 编辑:程序博客网 时间:2024/05/03 12:03

1、该二叉树为二叉搜索树。
这里写图片描述

二叉搜索树:如果左子树存在,其结点都比父结点小,如果右子树存在,其结点都比父结点大。

故从根结点开始与两个输入结点比较:
如果当前结点大于这两个结点时,那么这两个结点的最近公共祖先一定在当前结点的左子树中;
如果当前结点小于这两个结点时,那么这两个结点的最近公共祖先一定在当前结点的右子树中。

参考代码:

Node<T>* _GetlastcommonNode(Node<T>* root, int val1, int val2)    {        assert(root);        Node<T>* Cur = root;        while (Cur)        {            //当前结点大于这两个结点,故在左子树中找            if (Cur->_val > val1&&Cur->_val > val2)                Cur = Cur->_left;            //当前结点小于这两个结点,故在右子树中找            else if (Cur->_val < val1&&Cur->_val < val2)                Cur = Cur->_right;            //找到了            else                return Cur;        }        return NULL;    }

2、普通的二叉树,但除根结点外每个结点都有指向父结点的指针
这里写图片描述
例:找D和G的最近公共祖先
D存在在链表D->C->B->A中;
G存在在链表G->F->B->A中。
故此时求二叉树中两个结点的最近公共祖先问题转化为求两个链表的第一个公共结点。

参考代码:

//用于求链表长度int len(Node<T>* node)    {        assert(node);        Node<T>* cur = node;        int idx = 0;        while (cur)        {            idx++;            cur = cur->_parent;        }        return idx;    }
    Node<T>* _GetlastcommonNode(Node<T>* root, Node<T>* node1, Node<T>* node2)    {        assert(root);        assert(node1);        assert(node2);        int len1 = len(node1);        int len2 = len(node2);        Node<T>* cur1 = node1;        Node<T>* cur2 = node2;        int _len = len1 - len2;        if (_len > 0)        {            while (_len--)                cur1 = cur1->_parent;        }        else        {            _len = 0 - _len;            while (_len--)                cur2 = cur2->_parent;        }        while (cur1 != cur2)        {            cur1 = cur1->_parent;            cur2 = cur2->_parent;        }        return cur1;    }

3、普通的树,树中的结点没有指向父结点的指针

//找结点node的路径bool FindPath(Node<T>* root, Node<T>* node, stack<Node<T>*> &s)    {        if (root == NULL)            return false;        s.push(root);        if (root == node)            return true;        bool left = FindPath(root->_left,node,s);        bool right = FindPath(root->_right,node,s);        //结点node不在当前路径中        if (left == false && right == false)        {            s.pop();            return false;        }        return true;    }
Node<T>* _GetlastcommonNode(Node<T>* root, Node<T>* node1, Node<T>* node2)    {        //结点node1的路径        stack<Node<T>*> s1;        //结点node2的路径        stack<Node<T>*> s2;        FindPath(root,node1,s1);        FindPath(root,node2,s2);        //转化为求两个链表第一个公共结点的问题        int len = s1.size() - s2.size();        if (len > 0)        {            while (len--)                s1.pop();        }        else        {            len = 0 - len;            while (len--)                s2.pop();        }        while (!s1.empty() && !s2.empty() && s1.top() != s2.top())        {            s1.pop();            s2.pop();        }        return s1.top();    }
阅读全文
0 0
原创粉丝点击