2021-10-24树与森林

  • 求二叉树的宽度
  • queue.poll()
    poll()返回队首元素的同时删除队首元素,队列为空时返回NULL
int GetMaxWidth(BinaryTree pointer){
  if(pointer==null)
  {
    return 0;
  }
  Queue<BinaryTreeNode> queue=new ArrayDeque<BinaryTreeNode>();
  int maxWidth=1;//最大宽度
  queue.add(pointer);
  while(true)
  {
    int Size=queue.Size();//计算当前层的节点的个数
    if(Size==0)
    {
      break;
    }
    while(Size>0){//如果当前层还有节点就进行下去
      BinaryTreeNode node=queue.poll();
      Size--;
      if(node->leftChild)
        queue.add(node->leftChild);//当前节点的左子树入队
      if(node->rightChild)
        queue.add(node->rightChild);//当前节点的右子树入队
      maxWidth=Math.max(Size,queue.Size());
    }
  }
  return maxWidth;//返回计算所得的最大的二叉树的宽度。
}

参考:https://www.jb51.net/article/110569.htm
5-1
下列代码的功能是计算给定二叉树T的宽度。二叉树的宽度是指各层结点数的最大值。函数Queue_rear和Queue_front分别返回当前队列Q中队尾和队首元素的位置。

typedef struct TreeNode *BinTree;
struct TreeNode
{
   int Key;
   BinTree  Left;
   BinTree  Right;
};

int Width( BinTree T )
{
   BinTree  p;
   Queue Q;
   int Last, temp_width, max_width;

   temp_width = max_width = 0;
   Q = CreateQueue(MaxElements);
   Last = Queue_rear(Q);
   if ( T == NULL) return 0;
   else {
      Enqueue(T, Q);
      while (!IsEmpty(Q)) {
         p = Front_Dequeue(Q); 
         temp_width++;
; 
         if ( p->Left != NULL )  Enqueue(p->Left, Q);
         
         if ( p->Right != NULL )  Enqueue(p->Right, Q);
;  
         if ( Queue_front(Q) > Last ) {
            Last = Queue_rear(Q);
            if ( temp_width > max_width ) max_width = temp_width;
            
temp_width = 0
;
         } /* end-if */
      } /* end-while */
      return  max_width;
   } /* end-else */
} 
  • 7-1 树的同构 (25 分)
    1.怎么存
    用数组,用int型root标记树根
    2.怎么比
    ①两个都为空 ,同构
    ②一空一不空,异构, 两个树根节点不同,异构
    ③两个根节点的孩子分两种情况,一种是左孩子相等右孩子也相等,另一种是t1左孩子和t2右孩子相等
#include<iostream>
using namespace std;


typedef struct Tree
{
    char data;
    int lchild,rchild;
}Tree;
Tree t1[20],t2[20];
int BuildTree(Tree *t)
{
    int N,i,isChild[20] = {0};
    char e,l,r;
    cin>>N;
    if(N==0)
        return -1;
    for(i = 0; i<N; i++)
    {
        cin>>e>>l>>r;
        t[i].data = e;
        if(l == '-')
            t[i].lchild = -1;
        else
        {
            t[i].lchild = l-'0';
            isChild[l-'0'] = 1;
        }
         if(r == '-')
            t[i].rchild = -1;

        else
        {
             t[i].rchild = r-'0';
            isChild[r-'0'] = 1;
        }

    }
    for(i = 0; i<N;i++)
    {
        if(!isChild[i])
            return i;
    }
    cout<<endl;

}
int IsSameStruct(int r1,int r2)
{

    if(r1 == -1 && r2 == -1)//两棵都空
        return 1;
    if((r1 == -1||r2 == -1)||t1[r1].data != t2[r2].data)//一棵树空一棵不空//树根不同
        return 0;
    if((t1[r1].lchild != -1&&t2[r2].lchild != -1)&&(t1[t1[r1].lchild].data == t2[t2[r2].lchild].data))
        return IsSameStruct(t1[r1].lchild,t2[r2].lchild)&&IsSameStruct(t1[r1].rchild,t2[r2].rchild);
    else
        return IsSameStruct(t1[r1].lchild,t2[r2].rchild)&&IsSameStruct(t1[r1].rchild,t2[r2].lchild);
}
int main()
{
    int r1,r2;
    r1 = BuildTree(t1);
    r2 = BuildTree(t2);
    int flag = IsSameStruct(r1,r2);
    if(flag)
        cout<<"Yes";
    else
        cout<<"No";
}

7-2 家谱处理 (30 分)
人类学研究对于家族很感兴趣,于是研究人员搜集了一些家族的家谱进行研究。实验中,使用计算机处理家谱。为了实现这个目的,研究人员将家谱转换为文本文件。下面为家谱文本文件的实例:

John
Robert
Frank
Andrew
Nancy
David
家谱文本文件中,每一行包含一个人的名字。第一行中的名字是这个家族最早的祖先。家谱仅包含最早祖先的后代,而他们的丈夫或妻子不出现在家谱中。每个人的子女比父母多缩进2个空格。以上述家谱文本文件为例,John这个家族最早的祖先,他有两个子女Robert和Nancy,Robert有两个子女Frank和Andrew,Nancy只有一个子女David。

在实验中,研究人员还收集了家庭文件,并提取了家谱中有关两个人关系的陈述语句。下面为家谱中关系的陈述语句实例:

John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert
研究人员需要判断每个陈述语句是真还是假,请编写程序帮助研究人员判断。

输入格式:
输入首先给出2个正整数N(2≤N≤100)和M(≤100),其中N为家谱中名字的数量,M为家谱中陈述语句的数量,输入的每行不超过70个字符。

名字的字符串由不超过10个英文字母组成。在家谱中的第一行给出的名字前没有缩进空格。家谱中的其他名字至少缩进2个空格,即他们是家谱中最早祖先(第一行给出的名字)的后代,且如果家谱中一个名字前缩进k个空格,则下一行中名字至多缩进k+2个空格。

在一个家谱中同样的名字不会出现两次,且家谱中没有出现的名字不会出现在陈述语句中。每句陈述语句格式如下,其中X和Y为家谱中的不同名字:

X is a child of Y
X is the parent of Y
X is a sibling of Y
X is a descendant of Y
X is an ancestor of Y
输出格式:
对于测试用例中的每句陈述语句,在一行中输出True,如果陈述为真,或False,如果陈述为假。

输入样例:
6 5
John
Robert
Frank
Andrew
Nancy
David
Robert is a child of John
Robert is an ancestor of Andrew
Robert is a sibling of Nancy
Nancy is the parent of Frank
John is a descendant of Andrew
结尾无空行
输出样例:
True
True
True
False
False
结尾无空行
想法:这道题存是一个问题,然后提取问题,判断关系,判断关系里面有一个大坑就是可能会访问到祖宗的parent的name,由于祖宗的parent为NULL,故访问到它的name是就会出错
参考:https://blog.csdn.net/Deep___Learning/article/details/102623623?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163504940916780269817962%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163504940916780269817962&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-1-102623623.pc_search_result_cache&utm_term=%E5%AE%B6%E8%B0%B1%E5%A4%84%E7%90%86&spm=1018.2226.3001.4187

#include<iostream>
#include<string>
using namespace std;
typedef struct People
{
    string name;
    int flag;
    People *parent;
}People;
  People family[101];

int N;

int IsChild(string x,string y)
{
      int i;
      for( i = 0; i<N; ++i)
      {
          if(family[i].name == x)
            break;
      }
       if(family[i].parent == NULL)//如果x的父亲存在的话,才能访问parent的name,不然就会发生段错误
          return 0;
       else
       {
             if(family[i].parent->name == y)
               return 1;
            else
               return 0;
       }
}

int IsAncestor(string x,string y)
{
    int p1,p2,i;
    for(i = 0; i<N; ++i)
    {
        if(family[i].name == y)
            break;
    }
    People *p = family[i].parent;
    while(p)
    {
        if(p->name == x)
            return 1;
        p = p->parent;
    }
        return 0;

}
int IsSibling(string x,string y)
{
    int i;
    People *p;
    for(i = 0; i<N; ++i)
    {
        if(family[i].name == x)
        {
            p = family[i].parent;
            break;
        }
    }
     for(i = 0; i<N; ++i)
    {
        if(family[i].name == y)
        {
            if(p == family[i].parent)
                return 1;
            else
                return 0;
        }
    }
}

int IsParent(string x,string y)
{
    int i;
    for(i = 0; i<N; ++i)
    {
        if(family[i].name == y)
        {
            if(family[i].parent)
           {
            if(family[i].parent->name == x )
                return 1;
            else
                return 0;
           }
           else
             return 0;
        }
    }

}
int IsDescendant(string x,string y)
{
    int i,j;
    for(i = 0; i<N; ++i)
    {
        if(family[i].name == x)
            break;
    }//找到孩子
    if(family[i].parent == NULL)
        return 0;
    else
    {
        People *p = family[i].parent;
        while(p)
        {
            if(y == p->name)
                return 1;
            p = p->parent;
        }
        return 0;
    }
}
int main()
{
    int M,i;
    cin>>N>>M;
    getchar();//处理换行
    string str;
    for(i = 0; i<N; ++i)
    {
        getline(cin,str);
        int length = str.length();
        if(str[0] != ' ')//读入祖宗
        {
            family[i].name = str;
            family[i].flag = 0;
            family[i].parent = NULL;
        }
        else
        {
            int j,k,t;
            for(j = 0; j<length;++j)//过滤空格,找到名字的第一个位置
            {
                if(str[j] != ' ')
                    break;
            }
            for(k = j; k<length;++k)//存名字
                family[i].name += str[k];

            family[i].flag = j/2;//根据空格判断他是第几代人

            for(t = i - 1; t>=0; --t)//倒着找爸爸
            {

                if(family[t].flag == family[i].flag -1 )
                {
                    family[i].parent = family + t;

                    break;
                }
            }


        }
    }

//    for(i = 0; i<N;i++)
//    {
//        cout<<family[i].name<<endl;
//        cout<<family[i].parent->name<<endl;
//    }
    for(i = 0; i<M; ++i)
    {
        getline(cin,str);
        string x,y;
        int p = 0;
        int q = str.length() - 1;
        while(str[p] != ' ')
        {
            ++p;
        }
        for(int j = 0; j<p; ++j )
            x += str[j];

        while(str[q] != ' ')
        {
            --q;
        }
        for(int j = q+1; j< str.length(); ++j)
            y += str[j];

        int flag;
        switch(str[p+8])
        {
            case'i' :
                flag = IsChild(x,y);
                break;
            case'n':
                flag = IsAncestor(x,y);
                break;
             case'b' :
                flag = IsSibling(x,y);
                break;
            case'p':
                flag = IsParent(x,y);
                break;
            case's':
                flag = IsDescendant(x,y);
                break;
        }
        if(flag)
            cout<<"True"<<endl;
        else
            cout<<"False"<<endl;
    }

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值