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

编程入门 行业动态 更新时间:2024-10-26 16:25:19

树的<a href=https://www.elefans.com/category/jswz/34/1768060.html style=基本知识总结和上周做的题思路整理"/>

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

文章目录

  • 一、树的一些基本知识
    • 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 型,故不会出现问题。

更多推荐

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

本文发布于:2024-02-11 17:02:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1682161.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:基本知识   上周   思路

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!