pta——树最近公共祖先

记录数据结构pta作业,多有不足

题目

已知树结点为互不相等且不等于0的整数。请编写程序找出非空树中两个结点的最近公共祖先。例如对于图1(a)所示的树t,结点1和2的最近公共祖先是5;结点2和4的最近公共祖先是8。

tree.jpg

输入格式:

每个测试点包含多组数据,第1行为一个正整数T,表示数组组数。每组数据为2行,第1行为一组用空格间隔的整数,个数不超过100个,表示带空指针信息的二叉树先根序列。其中空指针信息用0表示。第2行为空格间隔的两个互不相等的整数A和B,表示给定的两个结点值,保证A和B肯定在输入的树中。

注:我们已知二叉树与其自然对应的树相比,二叉树中结点的左孩子对应树中结点的左孩子,二叉树中结点的右孩子对应树中结点的右兄弟。进而我们可以利用“带空指针信息的先根序列构建二叉树”的方法来构建其对应的树的左孩子-右兄弟存储结构。如8 5 1 0 6 0 2 0 0 3 4 0 0 7 0 0 0对应图1(a)所示的树,1 2 0 3 0 4 0 0 0对应如图1(b)所示的树。

输出格式:

对每组数据输出一行,为一个整数,表示A和B的最近公共祖先结点的值。

输入样例1:

2
8 5 1 0 6 0 2 0 0 3 4 0 0 7 0 0 0
1 2
8 5 1 0 6 0 2 0 0 3 4 0 0 7 0 0 0
2 4

输出样例1:

5
8

思路

  1. 结点构造包括左右孩子以及parent,用于孩子兄弟表示法(二叉树)
  2. 孩子兄弟表示法和二叉树类似,不过把rchild变成brother了
  3. 采取递归方式构造该树
  4. 根据孩子兄弟表示法,构造正常的树,由于孩子可能不止两个,我用队列存储每个孩子
  5. 一个结点下,child是其第一个孩子,child的brother是下一个孩子,直到brother为NULL
  6. 类似层次遍历,我采用队列,在第五步时,压入栈
  7. 最后找到指定数据所在位置,向上寻找,嵌套循环,输出最近parent

代码


#include<iostream>
#include<queue>
using namespace std;
typedef struct TNode{
    int data;
    struct TNode *child,*brother,*parent;
}TNode,*pNode;
typedef struct TNode2{
    int data;
    struct TNode2* parent;
    queue <TNode2*> child;
}TNode2,*pNode2;
pNode2 findIn(pNode2 root2,int num){
    //cout<<"find"<<endl;
    if(root2==NULL){
        return 0;
    }
    else{
        pNode2 p = root2;
        queue <pNode2> q;
        q.push(p);
        //cout<<"push"<<p->data<<endl;
        while(!q.empty()){
            pNode2 temp = q.front();
            q.pop();

            //cout<<"pop"<<temp->data<<endl;

            if(temp->data==num){
                return temp;
            }
            else{
                int n = temp->child.size();
                for(int i = 0; i < n; i++){
                    pNode2 node = new TNode2;
                    node->data = temp->child.front()->data;
                    node->parent = temp->child.front()->parent;
                    node->child = temp->child.front()->child;

                    temp->child.push(node);
                    


                    q.push(node);
                    //cout<<"push"<<node->data<<endl;

                    temp->child.pop();
                }
            }
        }
    }
}
void creatbroTree(pNode &node){
    int num;
    pNode p = node;
    cin >> num;
    if(num==0){
        return;
    }
    else{
        node = new TNode;
        node->data = num;
        node->brother = NULL;
        node->child = NULL;
        creatbroTree(node->child);
        creatbroTree(node->brother);
    }
}
pNode2 creatbiTree(pNode2 &root2,pNode &root1){
    //cout<<"creat"<<endl;
    if(root1==NULL){
        return NULL;
    }
        
    else{
        pNode2 par = root2;
        pNode cur = root1;
        queue <pNode2> q;
        queue <pNode> q1;

        pNode2 node = new TNode2;
        pNode2 re = node;
        node->data = root1->data;
        node->parent = par;
        par = node;

        q.push(par);
        //cout<<"push"<<par->data<<endl;

        q1.push(cur);


        while(!q.empty()){
            pNode2 temp = q.front();
            par = temp;
            q.pop();
            //cout<<"pop"<<temp->data<<endl;

            cur = q1.front();
            q1.pop();

            pNode p = cur->child;
            while(p!=NULL){
                q1.push(p);
                pNode2 node = new TNode2;
                node->data = p->data;
                node->parent = par;
                par->child.push(node);
                q.push(node);
                //cout<<"push"<<node->data<<endl;
                p = p->brother;
            }
        }
        return re;
    }
}
int main(){
    int n;int a,b;
    pNode pre=NULL;
    pNode2 pa=NULL;
    pNode2 pb=NULL;
    cin>>n;
    for(int i = 0; i < n; i++){
        pNode root1 = NULL;
        pNode2 root2 = NULL;
        creatbroTree(root1);
        root2 = creatbiTree(root2,root1);

        cin>>a>>b;
        pa = findIn(root2,a);

        pb = findIn(root2,b);
        pNode2 memory = pb;
        while(pa!=NULL){
            while(pb!=NULL){
                if((pa->data)==(pb->data)){
                    cout<<pa->data<<endl;
                    break;
                }
                pb = pb->parent;
            }
            if(pa==pb){
                break;
            }
            pa = pa->parent;
            pb = memory;
        }
    }
    system("pause");
    return 0;
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值