当前位置: 首页 > news >正文

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

目录

一.基础:

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CSP-J模拟赛day1——试题
  • 锁相环 vivado FPGA
  • centos中zabbix安装、卸载及遇到的问题
  • Pytest进阶之fixture的使用(超详细)
  • BGP之选路MED
  • 【科研】# Taylor Francis 论文 LaTeX template模版 及 Word模版
  • 【操作系统】解析线程安全中的 Synchronized 关键字
  • 【C++】:红黑树深度剖析 --- 手撕红黑树!
  • MySQL之索引及简单运用
  • 文本编辑三巨头(grep)
  • 【Node.js基础04】node.js模块化
  • 个人电脑网络安全 之 防浏览器和端口溢出攻击 和 权限对系统的重要性
  • C++ set
  • vue3学习记录1:emit的写法
  • java8函数式编程学习(二):optional,函数式接口和并行流的学习
  • [数据结构]链表的实现在PHP中
  • 4个实用的微服务测试策略
  • Bootstrap JS插件Alert源码分析
  • ES6--对象的扩展
  • Laravel核心解读--Facades
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • vagrant 添加本地 box 安装 laravel homestead
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 利用DataURL技术在网页上显示图片
  • 数据科学 第 3 章 11 字符串处理
  • MyCAT水平分库
  • Prometheus VS InfluxDB
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 正则表达式-基础知识Review
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • ​Redis 实现计数器和限速器的
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​你们这样子,耽误我的工作进度怎么办?
  • # SpringBoot 如何让指定的Bean先加载
  • #define 用法
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (Git) gitignore基础使用
  • (Python) SOAP Web Service (HTTP POST)
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (第三期)书生大模型实战营——InternVL(冷笑话大师)部署微调实践
  • (动态规划)5. 最长回文子串 java解决
  • (二)JAVA使用POI操作excel
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)母版页和相对路径