【説明する】树

开始树啦!

一、定义

一棵树是由n(n>0)个元素组成的有限集合,其中:

(1)每个元素称为结点(node);
(2)有一个特定的结点,称为根结点或树根(root);
(3)除根结点外,其余结点能分成m(m>=0)个互不相交的有限集合T0,T1,T2,……Tm-1。其中的每个子集又都是一棵树,这些集合称为这棵树的子树。

  eg(图)

 

二、性质

A.树是递归定义的;
B.一棵树中至少有1个结点
这个结点就是根结点,它没有前驱,其余每个结点都有唯一的一个前驱结点。
每个结点可以有0或多个后继结点。
因此树虽然是非线性结构,但也是有序结构。
至于前驱后继结点是哪个,还要看树的遍历方法,我们将在后面讨论;
C.一个结点的子树个数,称为这个结点的(degree,结点1的度为3,结点3的度为0);
度为0的结点称为叶结点(树叶leaf,如结点3、5、6、8、9);
度不为0的结点称为分支结点(如结点1、2、4、7);
根以外的分支结点又称为内部结点(结点2、4、7);

树中各结点最大值称为这棵树的度(这棵树的度为3)。


D.在用图形表示的树型结构中,
对两个用线段(称为树枝)连接的相关联的结点,称上端结点为下端结点的父结点,称下端结点为上端结点的子结点,称同一个父结点的多个子结点为兄弟结点
如结点1是结点2、3、4的父结点,结点 2、3、4是结点1的子结点,它们又是兄弟结点,同时结点2又是结点5、6的父结点。
称从根结点到某个子结点所经过的所有结点为这个子结点的祖先
如结点1、4、7是结点8的祖先。
称以某个结点为根的子树中的任一结点都是该结点的子孙。
如结点7、8、9都是结点4的子孙。
 E.定义一棵树的根结点的层次(level)为0,其它结点的层次等于它的父结点层次加1
如结点2、3、4的层次为1,结点5、6、7的层次为2,结点8、9的层次为3。
一棵树中所有的结点的层次的最大值称为树的深度(depth)。
如这棵树的深度为3。
 F.对于树中任意两个不同的结点,
如果从一个结点出发,自上而下沿着树中连着结点的线段能到达另一结点,称它们之间存在着一条路径。
可用路径所经过的结点序列表示路径,路径的长度等于路径上的结点个数减1
如上图中,结点1和结点8之间存在着一条路径,并可用(1、4、7、8)表示这条路径,该条路径的长度为3。
注意:
  ①不同子树上的结点之间不存在路径。
  ②从根结点出发,到树中的其余结点一定存在着一条路径。
 G.森林(forest)是m(m>=0)棵互不相交的树的集合。

三、树的遍历

在应用树结构解决问题时,往往要求按照某种次序获得树中全部结点的信息,这种操作叫作树的遍历
遍历的方法有多种,常用的有:

A、先序(根)遍历

  先访问根结点,再从左到右按照先序思想遍历各棵子树。
      原则:根——>左——>右
      如上图先序遍历的结果为:125634789;

B、后序(根)遍历

  先从左到右遍历各棵子树,再访问根结点。
      原则:左——>右——>根
      如上图后序遍历的结果为:562389741;

C、中序遍历

  先遍历左孩子,然后再遍历根节点,最后遍历右孩子
      原则:左——>根——>右
      如上图中序遍历的结果为:526138794

D、层次遍历

  按层次从小到大逐个访问,同一层次按照从左到右的次序。
      原则:从上到下,从左到右
      如上图层次遍历的结果为:123456789;

E、叶结点遍历

  有时把所有的数据信息都存放在叶结点中,而其余结点都是用来表示数据之间的某种分支或层次关系,这种情况就 用这种方法。
    原则:只询问每个叶子节点
      如上图按照这个思想访问的结果为:56389;

四、题目——找树根和孩子

【问题描述】

  给定一棵树,输出树的根root,孩子最多的结点max以及他的孩子

【输入格式】

  第一行:n(结点数<=100),m(边数<=200)。   
    以下m行;每行两个结点x和y,
    表示y是x的孩子(x,y<=1000)。

【输出格式】

 第一行:树根:root。   
 第二行:孩子最多的结点max。   
 第三行:max的孩子。

【输入样例】

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

【输出样例】

  4
  2
  6 7 8

上代码:

#include<cstdio>
using namespace std;

int tree[222],maxx=0,root,maxroot,n,m,x,y,g=0;
/*
    tree[]  :记录孩子所对的父亲编号 
    root    :树的树根编号 
    maxx    :孩子最多的结点个数
    maxroot :拥有最多孩子结点的根的编号 
    n :结点个数(n<=100)
    m :边数(m<=200)
    x :父亲(<=1000)
    y :孩子(<=1000)
*/
int main() {
    scanf("%d %d
",&n,&m);
    for(int i=1; i<=m; i++) { //分别有m种情况(谁是谁的孩子)
        scanf("%d %d
",&x,&y);
        tree[y]=x;//用tree数组存储孩子y的父亲为……
    }
    for(int i=1; i<=n; i++) {
        if(tree[i]==0) { //如果它没有父亲,则此数为树的根
            root=i;//用root记录下来
            break;
        }
        g=0;//循环n次,寻找最大孩子数,g记录
        for(int j=1; j<=n; j++) {
            if(tree[j]==i) g++;
            if(g>maxx) { //如果这一次的个数比maxx大,就用maxx记录下来
                maxx=g;
                maxroot=i;
            }
        }
    }
    printf("%d
%d
",root,maxroot);
    for(int i=1; i<=n; i++)
        if(tree[i]==maxroot)
            printf("%d ",i);
    return 0;
}

 

如果运气好也是错,那我倒愿意错上加错!

❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/6640493.html