判断二叉树是不是完全二叉树/求两节点最近的公共祖先

思路:
(1)判断一棵二叉树是否是完全二叉树,我们利用层序遍历的思想,设置标志位为true,先把根节点压进栈,再去看根的左孩子是不是存在,不存在将标志位设为false,再去遍历整棵树。

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

要求考虑以下三种种情况
1:二叉树每个节点有parent(三叉链)
思路:
根据两个节点分别找到自己的所有父节点直到根,并压入两个栈中,如果栈不为空从两个栈中取节点,如果相等先保存起来(防止返回多个公共祖先),如果有多个公共节点,Pop至最后一个相等的节点再返回。

2:二叉树是搜索二叉树。
思路:
搜索树的规律是,左孩子小于根,右孩子大于根,所以我们只需要递归去判定两个节点是不是某个节点的左右即可。

3:就是普通二叉树。(尽可能实现时间复杂度为O(N))
思路:
方法一:时间复杂度为O(N*N)
思路等同搜索二叉树,先序递归的方法。先递归去找两节点在树中的位置,如果在根节点的左右,则根节点就是这两节点的公共祖先。再去递归根的左子树和右子树。因为递归次数是N每次递归的次数是N所以时间复杂度为O(N*N)

方法二:时间复杂度为O(N)
先实现一个函数找到这两个节点,再让这两个节点及其所有父节点分别压入两个栈中,再去比较两个栈中的元素,从而找到最近的公共祖先节点。递归遍历一遍时间复杂度为O(N)

实现代码及测试代码

#include <iostream>
using namespace std;
#include <stack>
#include <queue>
#include <assert.h>

namespace BINARY
{
    struct Node
    {
        int elem;
        Node* left;
        Node* right;
        Node* parent;

        Node(int x)
            :elem(x)
            , left(NULL)
            , right(NULL)
            , parent(NULL)
        {}
    };
    //判断一个节点是不是在一棵树
    bool IsInTree(Node* root, Node* x)
    {
        assert(x);
        if (NULL == root)
            return false;

        if (root->elem == x->elem)
            return true;

        return  IsInTree(root->left, x) || IsInTree(root->right, x);
    }

    //判断一棵树是否是另外一棵树的子树
    bool IsSon(Node* tree1, Node* tree2)
    {

        if (tree2 == NULL)
            return true;

        if (tree1 == NULL)
            return false;

        if (tree1->elem != tree2->elem)
            return false;

        return IsSon(tree1->left, tree2->left) && IsSon(tree1->right, tree2->right);
    }
    bool IsSonTree(Node* tree1, Node* tree2)
    {
        bool ret = false;

        if (tree1 == NULL)
            return false;

        if (tree2 == NULL)
            return true;

        if (tree1 != NULL && tree2 != NULL)
        {
            if (tree1->elem == tree2->elem)
                ret = IsSon(tree1, tree2);
            if (!ret)
                ret = IsSonTree(tree1->left, tree2);
            if (!ret)
                ret = IsSonTree(tree1->right, tree2);
        }
        return ret;
    }

    //判断一棵树是不是完全二叉树,层序(使用队列)遍历二叉树,如果左为空,将tag置为false
    bool IsComplectTree(Node* root)
    {
        queue<Node*>  q;
        bool tag = true;
        if (root)
            q.push(root);

        while (!q.empty())
        {
            Node* front = q.front();
            q.pop();

            if (front->left)
            {
                if (tag == false)
                    return false;

                q.push(front->left);
            }
            else
            {
                tag = false;
            }

            if (front->right)
            {
                if (tag == false)
                    return false;

                q.push(front->right);
            }
            else
                tag = false;
        }
        //到这个位置队列为空,树层序遍历完了,返回空
        return true;
    }

    //求节点的公共祖先,若二叉树是搜索树
    Node* PublicAncestor1(Node* root, Node* x1, Node* x2)
    {
        if (NULL == root)
            return NULL;
        assert(x1 && x2);
        if (root->elem >= x1->elem && root->elem <= x2->elem || root->elem <= x1->elem && root->elem >= x2->elem)
            return root;
        else if (root->elem > x1->elem && root->elem > x2->elem)
        return   PublicAncestor1(root->left, x1, x2);
        else
        return  PublicAncestor1(root->right, x1, x2);
    }
    //求节点的公共祖先,若二叉树是三叉链
    Node* PublicAncerstor2(Node* root, Node* x1, Node* x2)
    {
        if (NULL == root)
            return NULL;
        assert(x1 && x2);
        stack<Node*> s1;
        stack<Node*> s2;
        Node* cur1 = x1;
        Node* cur2 = x2;

        while (cur1->parent != NULL)
        {
            if (cur1->parent->elem == x2->elem)
                return x2;
            cur1 = cur1->parent;
            s1.push(cur1);
        }

        while (cur2->parent != NULL)
        {
            if (cur2->parent->elem == x1->elem)
                return x1;
            cur2 = cur2->parent;
            s2.push(cur2);
        }

        Node* node = NULL;
        while (!s1.empty() && !s2.empty())
        {
            if (s1.top()->elem == s2.top()->elem)
                node = s1.top();
            else
                return node;
            s1.pop();
            s2.pop();
        }
        return node;

    }

    //求公共节点,二叉树为普通二叉树时间复杂度为O(n*n)
    Node* GetNodeAncestor(Node* root, Node* x1, Node* x2)
    {
        if (root == NULL)
            return NULL;
        assert(x1 && x2);

        if (x1 == root || x2 == root)
            return root;

        bool x1left, x1right, x2left, x2right;
        x1left = IsInTree(root->left, x1);
        x1right = IsInTree(root->right, x1);
        assert(x1left || x1right);

        x2left = IsInTree(root->left, x2);
        x2right = IsInTree(root->right, x2);
        assert(x2left || x2right);

        if (x1left && x2right || x1right && x2left)
            return root;
        else if (x1left && x2left)
            return GetNodeAncestor(root->left, x1, x2);
        else
            return GetNodeAncestor(root->right, x1, x2);
    }

    //求公共节点,二叉树为普通二叉树时间复杂度为O(n)
    bool GetNodePaths(Node* root, stack<Node*>& s, Node* x)
    {
        if (NULL == root)
            return false;

        s.push(root);
        if (x == root)
            return true;

        bool left = GetNodePaths(root->left, s, x);
        if (left)
            return true;

        bool right = GetNodePaths(root->right, s, x);
        if (right)
            return true;

        s.pop();
        return false;
    }


    Node* GetNodeAncestorN(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();
    }

    void test()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);

        n1->left = n2;
        n2->parent = n1;
        n1->right = n3;
        n3->parent = n1;
        n3->left = n4;
        n4->parent = n3;
        n3->right = n5;
        n5->parent = n3;

        Node* m1 = new Node(2);
        Node* m2 = new Node(4);
        Node* m3 = new Node(5);

        m1->left = m2;
        m1->right = m3;
        //Node* n6 = new Node(2);
        //cout << IsInTree(n1, n6)<<endl;
        //cout << IsSonTree(n1, m1) << endl;
        //cout << IsComplectTree(m1) << endl;
        Node* ret = GetNodeAncestorN(n1, n4, n5);
        cout << ret->elem << endl;

        cout << PublicAncerstor2(n1, n2, n5)->elem << endl;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值