C++树形结构(1 基础)

news2024/12/28 8:04:27

目录

一.基础:

1.概念:

2.定义:

Ⅰ.树的相关基础术语:

Ⅱ.树的层次:

3.树的性质:

二.存储思路:

1.结构体存储:

 2.数组存储:

三.树的遍历模板:

四.信息统计方式:

1.自顶向下统计:

2.自底向上统计

五.基础练习:


一.基础知识 :

1.概念:

在前面学过的存放数据的容器有:数组、链表、栈、队列等,这些都是线性结构,数据元素之间存在一对一的线性关系。但在实际生活中,往往是非线性关系,数据元素之间的关系通常可以一对多。所以必须要把这些数据关系储存下来。其实树形结构就像递归数一样。递归树中,都只能从父节点走到子节点。我们只需要记录每个父节点有哪些子节点,那么就可以遍历整个递归树。我们可以用动态数组(vector)来记录每个节点的子节点。这就是树的孩子表示法

2.定义:

Ⅰ.树的相关基础术语:

(1).根节点:最顶层的节点就是根结点,它是整棵树的源头,一般用root表示。如1

(2)叶子节点:在树最底端的节点,就是其子节点个数为0的节点。如4、7、6、3

(3).节点的度:指定节点有子节点的个数。如2的度为3

(4).无根树:没有指定根节点的树,树的形态多样。明显这里以1为根和以5为根,树的形态不一样。

(5).有根树:指定了根节点的树,树的形态唯一。

(6).森林:由多棵树构成

(7).链长:边权相加。

Ⅱ.树的层次:

(1).节点高度:指从这个节点到叶子节点的距离(一共经历了几个节点)。

(2).树的高度:指所有节点高度的最大值。

(3).节点的层:从根节点开始,假设根节点为第1层,根节点的子节点为第2层,依此类推

3.树的性质:

性质1:n个节点,保证任意两点有且仅有一条路径,树中有且仅有n-1条边。

证明:除第一个节点外,连接一个其他节点,至少增加一条边,所以n个点至少要用n-1条边才能保证所有节点连通。若此时再增加一条非重边,任意两点间是否还存在一条唯一路径。

性质2:树的根结点没有前驱(父节点),除根结点外的所有结点有且只有一个前驱。树中所有结点可以有零个或多个后继(子节点)。

证明:同上。

二.存储思路:

输入一个数字n表示一颗有n个点的树。接下来一行输入n个数,表示每个点上的权值ai。后面n-1行,每行输入三个数u,v,w,表示节点u,v存在一条边,边权为w。请把所有信息保存下来。

1.结构体存储:

用结构体把每个节点的信息进行封装。这样的优点在于节点信息非常独立,但是所占空间稍大。

struct node{
    int data;
    vector<int> v,w;
}a[105];
int main(){
    cin>>n;
    for(int i=1;i<+n;i++) cin>>a[i].data;
    for(int i=1;i<=n;i++){
        int x,y,z;cin>>x>>y>>z;
        a[x].v.push_back(y);
        a[y].v.push_back(x);
        a[x].w.push_back(z);
        a[y].w.push_back(z);
    }
}

 2.数组存储:

用多个数组,分别描述每个节点的对应信息。这种方式的有点在于速度稍快,写起来简单。

int data[105]
vector<int> v,w;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>data[i];
    for(int i=1;i<=n;i++){
        int x,y,z;cin>>x>>y>>z;
        v[x].push_back(y);
        v[y].push_back(x);
        w[x].push_back(z);
        w[y].push_back(z);
    }
}

三.树的遍历模板:

我们可以发现前两道例题都是有向的边,所以不担心会从子节点重新走到父亲节点。但是通常来讲,树的边都是双向的我们在遍历的时候不希望一个点遍历多次。我们可以用dfs中记录由父亲节点(来向),这样可以阻止走回去。

void dfs(int x,int fa){
    for(int i=0;i<v[x].size();i++){
        int y=v[x][i];
        if(x==fa) continue;
        dfs(y,x);
    }
}

四.信息统计方式:

1.自顶向下统计:

操作方法:在进入dfs之前进行信息统计。如求链长:树上两个节点必然有且仅有一条路径,我们可以把该路径看成一条链。路径上的边权和为两点的链长。

计算有根树中任意点到根节点的距离

int data[105];
void dfs(int x,int fa) {
	for(int i=0; i<v[x].size(); i++) {
		int y=v[x][i];
		if(y==fa) continue;
		data[y]=data[x]+w[x][i];
		dfs(y,x);
	}
}

扩展:输出有根树最长链的路径

在dfs时进行路径记录,用pre数组记录当前节点是由哪一个父亲节点走过来。
当找到最长链的终点,根据每个节点只有一个父亲。倒着找回去,就能输出完整路径。

int data[105],pre[105];
void dfs(int x,int fa) {
	for(int i=0; i<v[x].size(); i++) {
		int y=v[x][i];
		if(y==fa) continue;
		data[y]=data[x]+w[x][i];
		dfs(y,x);
	}
}
void print(int x){
    vector<int> r;
    for(int i=x;i>0;i=pre[i]) r.push_back(i);
    for(int i=r.size()-1;i>=0;i--) cout<<i<<" ";
}

2.自底向上统计

操作方法:在dfs回溯之时进行信息统计。如求树的节点个数:当前树上共有多少个节点。

子树的概念:抹除当前根节点以及所有与根节点的连边后,产生的树都是当前根节点的子树。
如当前根节点1的子树有,以2、3、4为根的子树。

计算有根树中各子树的节点个数:

int data[105];
void dfs(int x,int fa) {
    data[x]=1;
	for(int i=0; i<v[x].size(); i++) {
		int y=v[x][i];
		if(y==fa) continue;
		dfs(y,x);
        data[x]+=data[y];
	}
}

五.基础练习:

题目:

给定一棵有n个点的树(结点个数≤100),指定根节点为1。每个点带有点权。求以1为根节点的最大子树大小,以及最大影响力。影响力=该点权*该点向下的最大子树(这里的子树不包括从根节点来的部分)。

题目分析:

先用dfs求出每个各点的为根的节点个数(子树大小),用sz数组进行保存,并且在整个回溯过程中,不断比较节点1相连的几颗子树,求取最大值。

正确代码:

#include<bits/stdc++.h>
using namespace std;
int n,data[1001],s[1145],maxn;//data数组记录以i为根的子树大小
vector<int> v[105];
vector<int> w[105];
void dfs(int x,int fa){
	s[x]=1;
	for(int i=0;i<v[x].size();i++){
		int y=v[x][i];
		if(y==fa) continue;
		dfs(y,x);
		s[x]+=s[y];//记录点权相加
		maxn=max(s[y],maxn);//打擂台求最大
	}
}
int main() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>data[i];
	for(int i=1; i<n; i++) {
		int x,y;cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);
	cout<<maxn<<" ";
	maxn=0; 
	for(int i=1;i<=n;i++){
		maxn=max(s[i]*data[i],maxn);//打擂台求最大影响力
	}
	cout<<maxn;
	return 0;
}

树形结构(2 树的直径):C++树形结构(2 树的直径)-CSDN博客

 树形结构(3 树的中心、重心):C++树形结构(3 树的中心、重心)-CSDN博客

树形结构(总):https://blog.csdn.net/Archie28/article/details/140504428

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1947617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BUG】已解决:NameError: name ‘python‘ is not defined

NameError: name ‘python‘ is not defined 目录 NameError: name ‘python‘ is not defined 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于…

【TortoiseGit】合并单个commit(提交)到指定分支上

0、前言 当我们用Git的时候经常用到多个分支&#xff0c;会经常有如下情况&#xff1a;一个dev分支下面会有多个test分支&#xff0c;而每个test分支由不同的开发者。而我们会有这样的需求&#xff1a; 当某个test分支完成了相应功能验证&#xff0c;就要把成功验证的功能代码…

【Git】上传代码命令至codeup云效管理平台

通过git命令上传本地代码库至阿里的codeup云效管理平台的代码管理模块&#xff0c;使用方便&#xff0c;且比github上传网络环境要求低&#xff0c;超大文件&#xff08;>100M&#xff09;的文件也可以批量上传&#xff0c;且上传速度喜人。 目录 &#x1f337;&#x1f33…

[Vulnhub] Acid-Reloaded SQLI+图片数据隐写提取+Pkexec权限提升+Overlayfs权限提升

信息收集 IP AddressOpening Ports192.168.101.158TCP:22,33447 $ nmap -p- 192.168.101.158 --min-rate 1000 -sC -sV Not shown: 65534 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.7p1 Ubuntu 5ubuntu1.3 (Ubuntu Lin…

【NOI-题解】1009 - 数组逆序1162 - 数组元素的删除1211 - 数组元素的插入1161. 元素插入有序数组1159. 数组元素的移动

文章目录 一、前言二、问题问题&#xff1a;1009 - 数组逆序问题&#xff1a;1162 - 数组元素的删除问题&#xff1a;1211 - 数组元素的插入问题&#xff1a;1161. 元素插入有序数组问题&#xff1a;1159. 数组元素的移动 三、感谢 一、前言 本章节主要对数组问题中数组元素移…

昇思25天学习打卡营第23天 | 基于MindSpore的红酒分类实验

学习心得&#xff1a;基于MindSpore的红酒分类实验 在机器学习的学习路径中&#xff0c;理解和实践经典算法是非常重要的一步。最近我进行了一个有趣的实验&#xff0c;使用MindSpore框架实现了K近邻&#xff08;KNN&#xff09;算法进行红酒分类。这个实验不仅加深了我对KNN算…

Jenkins+Gitlab持续集成综合实战

一、持续集成应用背景&#xff1a; DevOps&#xff1a;&#xff08;英文Development&#xff08;开发&#xff09;和Operations&#xff08;技术运营&#xff09;的组合&#xff09;是一组过程、方法与系统的统称&#xff0c;用于促进开发&#xff08;应用程序/软件工程&#…

设计模式|观察者模式

观察者模式是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时&#xff0c;它的所有观察者都会收到通知并更新。观察者模式常用于实现事件处理系统、发布-订阅模式等。在项目中&#xff0c…

C语言 | Leetcode C语言题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; // 判断是否为完全平方数 bool isPerfectSquare(int x) {int y sqrt(x);return y * y x; }// 判断是否能表示为 4^k*(8m7) bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7; }int numSquares(int n) {if (isPerfect…

CSA笔记5-局域网yum源配置互联网yum源配置源代码编译安装

局域网yum源配置&#xff1a;建设一个本地网络仓库给本地局域网用户提供下载安装 互联网yum源配置&#xff1a;在线获取最新安装文件的通道 1.局域网web方式yum源配置&#xff1a; 服务器提供yum安装服务&#xff1a; yum install -y httpd 安装并启动httpd 在本地源的基…

Spring AOP(2)原理(代理模式和源码解析)

目录 一、代理模式 二、静态代理 三、动态代理 1、JDK动态代理 &#xff08;1&#xff09;JDK动态代理实现步骤 &#xff08;2&#xff09;定义JDK动态代理类 &#xff08;3&#xff09;代码简单讲解 2、CGLIB动态代理 &#xff08;1&#xff09;CGLIB 动态代理类实现…

RockyLinux 9 PXE Server bios+uefi 自动化部署 RockLinux 8 9

pxe server 前言 PXE&#xff08;Preboot eXecution Environment&#xff0c;预启动执行环境&#xff09;是一种网络启动协议&#xff0c;允许计算机通过网络启动而不是使用本地硬盘。PXE服务器是实现这一功能的服务器&#xff0c;它提供了启动镜像和引导加载程序&#xff0c;…

Java学习Day14:基础篇4

数组 1.理解数组 数组也是一种类型&#xff0c;引用类型&#xff01; 2.数组的定义 3.数组的初始化 静态&#xff1a; 动态&#xff1a; 不同数据类型数组初始化值&#xff1a; null不可用.equal方法&#xff0c;会报错&#xff01; 4.使用数组 5.foreach循环 6.深入数组 7&am…

绘制拟合联合密度分布

绘制拟合联合密度分布 import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KernelDensity# 生成模拟数据 np.random.seed(42) mean [0, 0] cov [[1, 0.5], [0.5, 1]] data np.random.multivariate_normal(mean, cov, size200) a data[:, 0…

基于jeecgboot-vue3的Flowable流程-自定义业务表单流程历史信息显示

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、对于自定义业务表单的流程历史记录信息做了调整&#xff0c;增加显示自定义业务表单 <el-tab-pane label"表单信息" name"form"><div v-if"customF…

德国云手机:企业移动办公解决方案

在现代商业环境中&#xff0c;移动办公已经成为一种趋势。德国云手机作为一种高效的解决方案&#xff0c;为企业提供了强大的支持。本文将探讨德国云手机如何优化企业的移动办公环境。 一、德国云手机的主要优势 高灵活性 德国云手机具有高度的灵活性&#xff0c;能够根据用户需…

鸿蒙HarmonyOS开发:用户通知服务Noification的详细使用指南

文章目录 一、Notification Kit简介二、能力范围三、业务流程四、通知样式&#xff1a;五、约束限制六、开发步骤6.1、导入模块。6.2、构造NotificationRequest对象&#xff0c;并发布通知。6.2.1、普通文本类型。6.2.2、长文本类型。6.2.3、多行文本类型。 6.3、为通知添加行为…

SpringBoot源码(1)ApplicationContext和BeanFactory

1、调用getBean方法 SpringBootApplication public class SpringBootDemoApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext SpringApplication.run(SpringBootDemoApplication.class, args);applicationContext.get…

javaFx 系统最小化托盘(及其避坑)、开机自启动

1、系统最小化托盘 参考资料&#xff1a; https://blog.51cto.com/u_14191/6310480 javafx 设置最小窗口大小 - Java (1) - 芒果文档 注意事项 1.直接使用第一个参考资料中的MinWindow类即可。 #最小化托盘 -- 一般放置在 start(Stage stage)处 MinWindow.getInstance().…

鸿蒙仓颉语言【cryptocj 库】(介绍与SHA、MD5、HMAC摘要算法)

cryptocj 库 介绍 cryptocj 是一个安全的密码库&#xff0c;包括常用的密码算法、常用的密钥生成和签名验证。 该库是对 C 语言的 openSSL 封装的仓颉加密算法 1 提供SHA、MD5、HMAC摘要算法。 前置条件&#xff1a;NA 场景&#xff1a; OHOS&#xff0c; Linux&#xff…