【c++提高1】树

大纲

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堂兄弟的数量。
输入输出样列
输入样例113 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


输出样例16

说明

数据范围: 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 >></
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

{∞}

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值