大纲
1.树的概念
2.树的存储
3.例题
4.树的先序遍历(DFS遍历)
5.例题
6.树的层次遍历(BFS遍历)
7.例题
1.树的概念
🔑引入Q:
题目描述
小Z无意中发现了一份家谱,家谱中记录了从小Z爷爷到小Z,共3代人的亲缘关系,请你帮Z科计算一下他有多少堂兄弟(小Z的堂兄弟是指和小Z共一个爷爷,但是不共一个爸爸,为计算方便,给出的家谱图中只包括男性成员)
输入格式
输入中,家庭成员的姓名使用整数编号表示,其中小Z爷爷的编号固定为1;
第一行:三个整数n, m和k,表示家谱中共有n个人,m条血缘关系,小科的编号是k;
接下来m行,每行两个用空格隔开的整数x和y。表示x是y的父亲。
输出格式
一行:一个整数,表示小Z堂兄弟的数量。
输入输出样列
输入样例1:
13 12 9
1 2
1 3
1 4
1 5
2 6
2 7
2 8
3 9
3 10
4 11
5 12
5 13
输出样例1:
6
说明
数据范围: n, k, m <= 100
小Z的堂兄弟和小科拥有同一个爷爷(双亲的双亲),不同的父亲(双亲结点)。
使用双亲表示法,记录下每个人的双亲。
枚举所有节点,如果其和小Z的双亲的双亲是同一人,且双亲不是同一人,那么他是小科的堂兄弟。
注意:树中堂兄的定义是,双亲在同一层(不是同一结点)的结点互为堂兄弟。
代码:
#include <bits/stdc++.h>
using namespace std ;
const int N = 110 ;
int n , m , k ;
int p[N] ;
int res , ps , zlayer ;
int x , y ;
int main ()
{
cin >> n >> m >> k ;
while (m -- ) cin >> x >> y , p[y] = x ;
zlayer = 1 , ps = p[k] ;
while (ps) zlayer ++ , ps = p[ps] ;
for (int i = 1; i < N; i++)
{
int ilayer = 1 , pi = p[i] ;
while (pi) ilayer ++ , pi = p[pi] ;
if (ilayer == zlayer && p[i] != p[k]) res ++ ;
}
cout << res ;
return 0 ;
}
树(Tree)是n(n ≥ 0)个结点的有限集。 n == 0时称为空树。在任意一棵非空树中:
树中的元素称为:结点。
有且仅有一个称为根(Root)的结点,如图中的A结点。
当n > 1时,根以外的结点可分为m(m > 0)个互不相交的有限集,其中每一个集合本身又是一棵树,并且称为根的子树 。
树的定义是递归的,树的子树也是一棵树,子树的子树也是一棵树。
【节点和度】
树的结点包含一个数据元素及若干指向其子树的分支。
结点拥有的子树(分支)数量称为结点的度。
度为0的结点称为叶子结点(Leaf)或终端结点。
度不为0的结点称为非终端结点或分支结点,除根结点以外,分支结点也称为内部结点。
树的度是树内各结点的度的最大值。示例中图的度 = 结点A的度 = 3。
【节点之间的关系】
孩子和双亲:结点的子树的根称为该节点的孩子,该节点称为其孩子的双亲(Parent)。
兄弟:同一个双亲的孩子之间互称兄弟。
祖先:结点的祖先是从根到该结点所经分支上的所有节点(自己也是自己的祖先)。
【层次和深度】
层次:结点的层次(Level)从根开始定义,根为第1层,根的孩子为第2层,以此类推。
若某节点在第i层,则其孩子结点就在第i+1层。
双亲在同一层的结点互为堂兄弟。
树中节点的最大层次称为树的深度(Depth)或高度。
【有序树和无序树 & 森林】
如果树中节点的各子树从左到右是有次序的,不能互换的,则称该树为有序树,否则称为无序树。
森林是m (m ≥0)棵互不相交的树的集合。
3.树的存储
【双亲表示法】
树中除了根结点以外,每个结点都有且仅有一个双亲结点,可以用一组连续的空间存储树的结点,同时在每个结点中,附设一个指示器指示其双亲的位置。也就是说,每个结点除了知道自己是谁以外,还知道它的双亲在哪里。
const int N = 1010 ;
struct Tree
{
char data ;
int parent ;
} tree[N] ;
优点:对于任意结点x,可以很方便的找到其双亲结点、祖先结点和根结点(向上查找)。
缺点:对于任意结点x,如果要查找其所有的孩子结点,需要遍历所有结点。
示例:找双亲
【问题描述】输入一颗树的描述,接下来有q次询问,每次询问给定一个结点,输出其双亲结点。
输入格式:
第一行:三个整数n(n ≤ 26), m, q, 表示有n个结点, m条关系, q次询问。
接下来m行,每行两个字符x, y,表示x是y的双亲结点,数据保证合法。
接下来q行,每行一个字符x,询问x的双亲结点。
输出格式:
q行,每行对应一次询问的结果。
核心代码:
struct Tree
{
char data ;
int parent ;
} tree[N] ;
int n , m , q ;
int main ()
{
cin >> n >></