1、复习二叉树的相关知识点:
(1)结点的度:结点拥有的子树个数
树的度:树中各结点中度的最大值
度为0的结点是叶子结点
(2)树的深度:树当中结点的最大层次
(3)有序树:树中各结点的子树从左至右是有次序的,如果子树变化,会变成另外一个树
无序树:树中结点的各子树无次序
(4)森林:是m各互不相交的树的集合(m>=0)把树的根节点删除就变成了森林,一棵树可以看成一个特殊的森林,给森林中的各子树加上一个双亲结点,森林就会变成子树。树一定是森林,森林不一定是树 。
总结一下,树形结构和线性结构之间有什么区别:
线性结构:第一个数据元素是没有前驱的,最后一个元素是没有后继的,其他数据元素是只有一个前驱只有一个后继的 元素之间的关系是一对一的
树形结构:根节点是只有一个的,是没有双亲的。叶子结点,可以有多个,也是没有孩子的(也就是没有后继),其他结点(也就是中间结点)只有一个双亲但是有多个孩子的 元素之间的关系是一对多的
(5)二叉树的定义:二叉树是有n个结点的有限集合,或者是空集合(也就是一个空树)或者是由一个根节点以及两个不相交的(称为左子树和右子树)的二叉树组成
特点:
每个节点最多有两个孩子(二叉树中不存在度大于2的结点)0 1 2
二叉树的子树有左右之分,次序不能颠倒、
二叉树可以是空集合,根可以有空的左子树或者右子树
3个结点的二叉树可能有几种不同的形态 (根据层次来判断会更快)
暂复习到这里,先看一道题目,关于完全二叉树的,
洛谷:P8681 [蓝桥杯 2019 省 AB] 完全二叉树的权值
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是 11。首先观察完全二叉树,第i层的节点个数应该是2^(i-1),第i层的最后一个节点的序号应该是2^i-1,根据这个性质进行解决,;
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N];
long long n,maxn,dep=1,sum,ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum=sum+a[i];
if(sum>maxn){
maxn=sum;
ans=dep;
}
dep++;
sum=0;
}
if(sum>maxn){
maxn=sum;
ans=dep;
}
cout<<ans<<endl;
return 0;
}
2、复习一个简单的dp问题,杭电的免费馅饼
都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:
为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)
Input
输入数据有多组。每组数据的第一行为以正整数n(0<n<100000),表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T(0<T<100000),表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。
Output
每一组输入数据对应一行输出。输出一个整数m,表示gameboy最多可能接到m个馅饼。
提示:本题的输入数据量比较大,建议用scanf读入,用cin可能会超时。
Sample Input
6
5 1
4 1
6 1
7 2
7 2
8 3
0
Sample Output
4
解决思路:联想到一个三叉树的问题,树塔问题
#include<iostream>
#include<cstring>
using namespace std;
int n,maxn=-1000,dep;
const int N=100008;
int x[N],y[N],dp[N][20];
int main(){
while(scanf("%d",&n)!=EOF){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%d %d",&x[i],&y[i]);
dp[y[i]][x[i]]++;
dep=max(maxn,y[i]);
}
for(int i=dep-1;i>=1;i--){
dp[i][0]+=max(dp[i+1][0],dp[i+1][1]);
for(int j=1;j<10;j++){
dp[i][j]+=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1]);
}
//来处理右边界问题
dp[i][10]+=max(dp[i+1][10],dp[i+1][9]);
}
cout<<max(max(dp[1][4],dp[1][5]),dp[1][6])<<endl;
}
return 0;
}