树的基本知识总结和上周做的题思路整理

2023-11-21 13:40

本文主要是介绍树的基本知识总结和上周做的题思路整理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、树的一些基本知识
    • 1.基本知识
    • 2.二叉树
      • a.基本知识
      • b.特殊二叉树
      • c.二叉树的性质
      • d.二叉树的遍历
  • 二、练习题整理
    • 1.智力题 crossing river
    • 2.剪花布条(kmp


一、树的一些基本知识

1.基本知识

a)理解:线性结构是一对一的关系,而树是一对多的关系,具有n(n>=0)个结点。

b)结点的分类:
根节点:无前驱的结点,A
叶子结点:或叫终端结点,度为0(有双亲无孩子
GHIJF都是
内部结点:有前驱有后继的结点,BCDE

一个填空题,已知结点数,结点数-1就是分枝儿个数;同样已知分枝儿个数+1就是结点数。可以看做一个结点跟着一个分枝,但根节点无前驱。
在这里插入图片描述

2.二叉树

a.基本知识

二叉树定义:二叉树是n(n>=n)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两棵互不相交的、分别称为根节点的左子树右子树的二叉树组成。在这里插入图片描述
个人理解:二叉树每个结点最多有两棵子树,也就是度取0,1,2,且按顺序分为左子树和右子树。但如果把二叉树和有序树等价我认为是错误的。对于下图两种情况有序树 树1=树2,而对于二叉树而言这是两种二叉树。在这里插入图片描述

b.特殊二叉树

1.斜树:每一层都只有一个结点,结点个数和二叉树的深度相同。
2.满二叉树:所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上。
3.完全二叉树:满二叉树一定是完全二叉树,二叉树按层序编号,先左子树后右子树,有一定的顺序,编号连续无空档。

c.二叉树的性质

性质1:在二叉树的第i层上至多有2^(i-1)个结点(i>=1)

性质2:深度为k的二叉树至多有2^k-1个结点(k>=1)

性质3:终端结点数为n0,度为2的结点数n2,则n0=n2+1;
联立 n=n0+n1+n2;和n-1=n1+2*n2;

性质3:深度为k的,有n个节点的完全二叉树,当且仅当没一个节点都与深度为k的满二叉树中编号从1至n的节点 一一对应。最后一层:叶子节点尽力靠左。具有n个节点的完全二叉树的深度必为(log2 n)+1。

d.二叉树的遍历

1.前序遍历:先访问根节点,然后前序遍历左子树,再前序遍历右子树。若为空则空操作返回。
简单理解就是先访问父结点,顺序是父节点→长子→次子
偷来大话数据结构的图来理解在这里插入图片描述
悟一下,都是先父后长子次子,也是有迭代套娃的意思。
中序遍历:先访问长子,再访问父结点,再次子
在这里插入图片描述
3.后序遍历: 长子→次子→父结点
前中后序的命名是根据父结点放在什么时候遍历而命名的。在这里插入图片描述
4.层序遍历:从根节点开始一层一层,也是先左娃后右娃跑。

二、练习题整理

1.智力题 crossing river

虽然这个题再看是挺简单的,但…总之是蛮改善我码代码的逻辑和思路的…贴上来(以及明白血压升高和松口气的感受 绿色永远滴神!!) 不谝了,贴题贴代码

题目简述:题目大致意思就是有一群人要过河,只有一艘船,一艘船只能乘两个人,每个人过河有各自的过河时间,如果两个人一起过河那么用时按时间长的那个人算,然后求这群人都成功过河用的最短过河时间。(注意还得有人把船划回来
input:The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains N, and the second line contains N integers giving the time for each people to cross the river. Each case is preceded by a blank line. There won’t be more than 1000 people and nobody takes more than 100 seconds to cross.(突然懒惰

output:For each test case, print a line containing the total number of seconds required for all the N people to cross the river.

Sample Input

1
4
1 2 5 10

Sample Output

17

思路是首先可以想到最小的那个一直做船夫运送人,这显然是一种方法。但假设是1 4 5 6,则会有更优的解决办法。即让最小的两个人做船夫,然后运送人,两个最胖胖先运走。
但一个方法不会一直用,寻找该问题的最小子问题,这个题中找循环规律,每一次循环会送走两个人,判断比较该循环中法1用时短还是法2用时短,ans+=即可
当然首先要判断n=1,2,3的特殊情况

贴上来源代码:

#include<stdio.h>
int n;
int a[1009];
int bubblesort(int a[]) //用冒泡排序进行排序
{int i,j,temp;for(i=0;i<n-1;i++){for(j=0;j<n-i-1;j++){if(a[j]>a[j+1]){temp=a[j];a[j]=a[j+1];a[j+1]=temp;}}}
}
int main()
{int t;scanf("%d",&t);int j;while(t--) //t组人{scanf("%d",&n);//int a[1009];int i;for(i=0;i<n;i++){scanf("%d",&a[i]);}bubblesort(a); //对时间长短进行排序int time1,time2;//两种方法int ans=0;while(n){ //n-=2直到n<=0为止跳出循环if(n==0) {ans=0;n=0;}else if(n==1) {ans+=a[0];n=0;} else if(n==2){ans+=a[1];n=0;}else if(n==3){ans+=a[0]+a[1]+a[2];n=0;}else{time1=a[n-1]+a[0]+a[n-2]+a[0];time2=a[1]+a[0]+a[n-1]+a[1];if(time1<time2) ans+=time1;else ans+=time2;n-=2; //踢去两个胖胖}}printf("%d\n",ans);//写个换行符}return 0;
}

注意按n分类就一直按n分类orz
另外,可以写

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;

或者直接

#include<bits/stdc++.h>
using namespace std;`

然后可以用sort(a,a+n),a是数组名,n是数组长度,智能排序

2.剪花布条(kmp

题目:一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢?

input:输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。
output:输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。

Sample Input

abcde a3
aaaaaa aa
#.

Sample Output

0
3

直接上源代码

#include<stdio.h>
#include<string.h>//KMP下标从0开始存储 
int getNext(char small[],int next[])
{int t=-1;//模式串(用来指示最长公共前缀 int j=0;//用来指示最长公共后缀 int lensmall;lensmall=strlen(small);next[0]=-1;//规定0号位置为-1(若下标从1开始则规定为0 while(j<lensmall-1)//不超过模式串长度 {if(t==-1 || small[t]==small[j]){//next[j+1]=t+1;++t;++j;next[j]=t;//规定next[j+1]=t+1(这里其实是对t的定义 }else t=next[t];//可以把j指示的模式串看成新的主串 }
}
int KMP(char big[],char small[],int next[]){int i=0;//指示主串,下标从0开始 int j=0;//指示模式串,下标从0开始 int ans=0; int lensmall,lenbig;lensmall=strlen(small);lenbig=strlen(big); //strlen()有学问 while(i<lenbig)//不超过主串长度 {if(j==-1 || big[i]==small[j]){++i;++j;}//逐一匹配 else j=next[j];//应用next数组,可以实现指示主串i不回溯 if(j>lensmall-1) ans++;//输出可以剪出多少个(即匹配成功多少次 }return ans;//记得一定要返回ans,否则答案为0 }
int main()
{int next[10010];char big[1000010];char small[10010];//按照题意开范围,千万别开小了 int a[1010]={0}; //作用在输出上 int ans;int i=0;int j;while(scanf("%s",big)){if(big[0]=='#') break;scanf("%s",small);getNext(small,next);ans=KMP(big,small,next);a[i]=ans;i++;//利用while循环将ans以此放入a数组中 j=i;//记录a数组的长度 }for(i=0;i<j;i++){printf("%d\n",a[i]); }//按照题意循环输出 
return 0;} 

(这是我写注释最多的一次,以后也要好好写注释XD

写这个代码的时候两个问题点
1是要抓住问题的输入输出格式,好好地去实现,不然代码对也会WA
2.关于strlen的问题
首先看下面两个代码(摘自上述源代码

int lensmall=strlen(small);
if(j>lensmall-1) ans++;
if(j>strlen(small)-1) ans++;

第一个代码正确,第二个会报错
经过百度strlen()知 strlen返回的是无符号整数值,而int 返回的是有符号整数值。源代码中的 j 会有取值-1的情况,而-1 无法直接和strlen()比较,会默认为1处理从而报错。 而第一个代码中的lensmall已经是一个int 型,故不会出现问题。

这篇关于树的基本知识总结和上周做的题思路整理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/402674

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

状态dp总结

zoj 3631  N 个数中选若干数和(只能选一次)<=M 的最大值 const int Max_N = 38 ;int a[1<<16] , b[1<<16] , x[Max_N] , e[Max_N] ;void GetNum(int g[] , int n , int s[] , int &m){ int i , j , t ;m = 0 ;for(i = 0 ;

go基础知识归纳总结

无缓冲的 channel 和有缓冲的 channel 的区别? 在 Go 语言中,channel 是用来在 goroutines 之间传递数据的主要机制。它们有两种类型:无缓冲的 channel 和有缓冲的 channel。 无缓冲的 channel 行为:无缓冲的 channel 是一种同步的通信方式,发送和接收必须同时发生。如果一个 goroutine 试图通过无缓冲 channel