• careercup-树与图 4.7


    4.7 设计并实现一个算法,找出二叉树中某两个结点的第一个共同祖先。不得将额外的结点储存在另外的数据结构中。注意:这不一定是二叉查找树。

    解答

    本题的关键应当是在Avoid storing additional nodes in a data structure 这句话上。我的理解是,不允许开额外的空间(比如说一个数组)来存储作为中间变量的结点。 虽然我也怀疑它是不是说不允许在结点数据结构Node中加入额外的东西, 比如说父结点的指针。Anyway,我们先从最简单的入手,再一步步加入限制条件。

    如果没有任何限制条件,那我觉得最直观的思路就是把其中一个点的所有祖先(包含它自身) 都放入一个哈希表,然后再一步步查找另一个点的祖先结点, 第一个在哈希表中出现的祖先结点即为题目所求。

    代码如下,用map模拟(当然,效率比不上哈希表):

    算法:

    //要使用额外的空间
    BinarySearchTree* findFirstAncestor(BinarySearchTree *x,BinarySearchTree *y)
    {
        if(x==NULL||y==NULL)
            return NULL;
        map<BinarySearchTree*,bool> mp;
        while(x)
        {
            mp[x]=true;
            x=x->parent;
        }
        while(y)
        {
            if(mp[y])
                return y;
            y=y->parent;
        }
        return y;
    }

    这里用了一个map来存储中间变量,如果题目不允许开额外的辅助空间,那该如何做呢? 那就老老实实地一个个地试。不断地取出其中一个结点的父结点, 然后判断这个结点是否也为另一个结点的父结点。代码如下:

    bool father(BinarySearchTree *x,BinarySearchTree *y)
    {
        if(x==NULL||y==NULL)
            return false;
        if(x==y)
            return true;
        return father(x->left,y)||father(x->right,y);
    }
    //将每一x的祖先拿出来判断是否为y的祖先,从下到上的方法
    BinarySearchTree* find_first_ancestor(BinarySearchTree *x,BinarySearchTree *y)
    {
        while(x)
        {
            if(father(x,y))
                return x;
            x=x->parent;
        }
        return x;
    }

    让我们把条件再限制地严苛一些,如果数据结构Node中不允许有指向父亲结点的指针, 那么我们又该如何处理?其实也很简单,首先根结点一定为任意两个结点的共同祖先, 从根结点不断往下找,直到找到最后一个这两结点的共同祖先,即为题目所求。代码如下:

    BinarySearchTree* find_ancestor(BinarySearchTree *root,BinarySearchTree *x,BinarySearchTree *y,BinarySearchTree *&ret)
    {
        if(x==NULL||y==NULL)
            return NULL;
        if(root&&father(root,x)&&father(root,y))
        {
            ret=root;
            find_ancestor(root->left,x,y,ret);
            find_ancestor(root->right,x,y,ret);
        }
        return ret;
    }

    这里用到了递归,ans最终保存的是这两个结点从根结点算起最后找到的那个祖先。 因为从根结点开始,每次找到满足要求的结点,ans都会被更新。

    C++完整代码:

    #include<iostream>
    #include<new>
    #include<map>
    using namespace std;
    
    struct BinarySearchTree
    {
        int elem;
        BinarySearchTree *parent;
        BinarySearchTree *left;
        BinarySearchTree *right;
        BinarySearchTree(int x):elem(x),parent(NULL),left(NULL),right(NULL) {}
    };
    
    void insert(BinarySearchTree *&root,int z)
    {
        BinarySearchTree *y=new BinarySearchTree(z);
        if(root==NULL)
        {
            root=y;
            return;
        }
        else if(root->left==NULL&&z<root->elem)
        {
            root->left=y;
            y->parent=root;
            return;
        }
        else if(root->right==NULL&&z>root->elem)
        {
            root->right=y;
            y->parent=root;
            return;
        }
        if(z<root->elem)
            insert(root->left,z);
        else
            insert(root->right,z);
    }
    
    void createBST(BinarySearchTree *&root)
    {
        int arr[10]= {29,4,6,1,8,3,0,78,23,89};
        for(auto a:arr)
            insert(root,a);
    }
    
    void inorder(BinarySearchTree *root)
    {
        if(root)
        {
            inorder(root->left);
            cout<<root->elem<<" ";
            inorder(root->right);
        }
    }
    
    BinarySearchTree* findMin(BinarySearchTree *root)
    {
        if(root==NULL||!root->left)
            return root;
        while(root->left)
        {
            root=root->left;
        }
        return root;
    }
    
    BinarySearchTree* findMax(BinarySearchTree *root)
    {
        if(root==NULL||!root->right)
            return root;
        while(root->right)
        {
            root=root->right;
        }
        return root;
    }
    
    BinarySearchTree* findProcessor(BinarySearchTree* x)
    {
        if(x->left)
            return findMax(x->left);
        BinarySearchTree *y=x->parent;
        while(y&&y->left==x)
        {
            x=y;
            y=x->parent;
        }
        return y;
    }
    
    BinarySearchTree* findSuccessor(BinarySearchTree *x)
    {
        if(x->right)
            return findMin(x->right);
        BinarySearchTree *y=x->parent;
        while(y&&y->right==x)
        {
            x=y;
            y=x->parent;
        }
        return y;
    }
    //要使用额外的空间
    BinarySearchTree* findFirstAncestor(BinarySearchTree *x,BinarySearchTree *y)
    {
        if(x==NULL||y==NULL)
            return NULL;
        map<BinarySearchTree*,bool> mp;
        while(x)
        {
            mp[x]=true;
            x=x->parent;
        }
        while(y)
        {
            if(mp[y])
                return y;
            y=y->parent;
        }
        return y;
    }
    bool father(BinarySearchTree *x,BinarySearchTree *y)
    {
        if(x==NULL||y==NULL)
            return false;
        if(x==y)
            return true;
        return father(x->left,y)||father(x->right,y);
    }
    //将每一x的祖先拿出来判断是否为y的祖先,从下到上的方法
    BinarySearchTree* find_first_ancestor(BinarySearchTree *x,BinarySearchTree *y)
    {
        while(x)
        {
            if(father(x,y))
                return x;
            x=x->parent;
        }
        return x;
    }
    //从上到下的方法
    BinarySearchTree* find_ancestor(BinarySearchTree *root,BinarySearchTree *x,BinarySearchTree *y,BinarySearchTree *&ret)
    {
        if(x==NULL||y==NULL)
            return NULL;
        if(root&&father(root,x)&&father(root,y))
        {
            ret=root;
            find_ancestor(root->left,x,y,ret);
            find_ancestor(root->right,x,y,ret);
        }
        return ret;
    }
    
    BinarySearchTree* search(BinarySearchTree* head, int x)
    {
        if(head == NULL) return NULL;
        if(x == head->elem)
            return head;
        else if(x <= head->elem)
            return search(head->left, x);
        else
            return search(head->right, x);
    }
    int main()
    {
        BinarySearchTree *root=NULL;
        createBST(root);
        inorder(root);
        cout<<endl;
        BinarySearchTree *n1 = search(root, 0);
        BinarySearchTree*n2 = search(root, 4);
        cout<<n1->elem<<" "<<n2->elem<<endl;
        BinarySearchTree *ans = find_first_ancestor(n1, n2);
        cout<<ans->elem<<endl;
        BinarySearchTree *ans1 = NULL;
        find_ancestor(root, n1, n2, ans1);
        cout<<ans1->elem<<endl;
        BinarySearchTree *pre=findProcessor(n2);
        cout<<pre->elem<<endl;
        BinarySearchTree *post=findSuccessor(n2);
        cout<<post->elem<<endl;
        return 0;
    }
  • 相关阅读:
    win7颜色反转
    全框眼镜拆卸镜片方法分享
    自定义锁屏图片 win7
    保存chrome主题背景的图片
    广域网设计
    网络方案设计
    电脑不能上网win7 解决办法
    局域网设计
    以太网安全技术ACL原理+配置
    协议无关组播--稀疏模式 PIM-SM
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4148195.html
Copyright © 2020-2023  润新知