文章目录
1、树的定义
2、树的类型
3、树形结构内的公式
4、使用树的方法
5、树的应用


一、树的定义

树,是一种突破链形的数据结构。像之前学的数组,栈,队列等都属于链形结构。二维数组也是链形的,就是由几条横线和竖线组成的矩形。

把它叫做树,是因为它像一棵倒着的树。而在中国,它应该叫“族谱”。其实,在树中的节点就是叫“父节点”这样的词(好像扯得太远了)。

树中最上的节点叫做“根”,除根以外的元素也构成了树,它们叫做子树。

子树的子节点个数,叫做这个节点的度。

度为0的节点,叫做叶子节点(没有儿子的节点)。

树的度,是最大的节点的度数(有几个儿子)。

树的深度,是树中最多子孙的深度。

x叉树:树中最多有几度。


二、树的类型

一、满二叉树:

定义:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。

重要公式:
1、满二叉树层数为k,则总节点个数为(2^k)-1。
2、满二叉树第i层上的结点数为2^(i-1)。
3、满二叉树的叶子结点个数为(2^k)-1。


二、完全二叉树:
定义:
满二叉树是完全二叉树的特殊形态, 即如果一棵二叉树是满二叉树, 则它必定是完全二叉树

重要公式:
一、具有n个结点的完全二叉树的深度为:*trunc(log2k)+1。
二、令1节点为i,则左儿子为2i,右儿子为2i+1。

注:trunc的意思是去小数点取整。


三、字典树

定义:它又叫做单词查找树(像哈希表,只不过比哈希表省时间)

举个例子:查询单词younger后,再查找young,就不用查到底了。但哈希查younger要先查一次,查young时还要再查一次,就比字典树浪费时间。


三、树形结构的公式

引用https://www.cnblogs.com/stemon/p/4775247.html

对于一棵二叉树,设叶子节点个数为n0,度为1的节点个数为n1,度为2的节点个数为n2。
则:n0+n1+n2=n

又由于除了根节点以外,每一个结点都占有一个边,
所以:n-1=2*n2+n1

综合上面的两个公式得到:
叶子结点和二度结点数目关系:n0=n2+1,n2=n0-1。

n个节点的二叉树一共有:(2n)! / n! * (n+1)!
注:’/'是除以的意思,!是阶乘的意思(123*4…n)。

一个完全二叉树的节点为n,则该二叉树的叶子节点为:1/2*n


四、使用树的方法

一:存储
(1):使用struct(不管是不是完全二叉树)

struct node {char data;int left;int right;
}tree[10011];//创建树节点,左右儿子节点
......
for (.../*分题目情况*/)cin >> tree[i].data >> tree[i].left >> tree[i].right;

(2):使用数组
如果是完全二叉树(直接存储):

自己画的哈(太丑请谅解)


如果不是完全二叉树(把空的地方用’#'表示):


二:输出前、中、后序

void visit_left (int Root) {//创立根if (Root == 0) return; //根为0,返回cout << tree[Root].data;//输出当前位置visit_left (tree[Root].left);//递归左儿子visit_left (tree[Root].right);//递归右儿子
}//树的前序(根、左、右)
void visit_mid (int Root) {if (Root == 0) return;visit_left (tree[Root].left);//递归左儿子cout << tree[Root].data;//输出当前位置visit_left (tree[Root].right);//递归右儿子
}//树的中序(左、根、右)
void visit_right (int Root) {if (Root == 0) return;visit_left (tree[Root].left);//递归左儿子visit_left (tree[Root].right);//递归右儿子cout << tree[Root].data;//输出当前位置
}//树的后序(左、右、根)

三:前、中、后转换

我来填坑啦啦啦

例:先中求后
思路:先求根(字符串第一位)。接着把这棵树分成左子树和右子树,把左子树求根。然后把这棵子树分成左子树和右子树,把左子树求根…
你会发现,这就是递归的运行方式!!!
所以,我们只要不断求根,接着不断递归左子树和右子树,就可以求后序啦!

void front_mid_to_behind (string front , string mid) { //先中求后 if (front.size() > 0) { //递归终止条件 char Root = front[0]; //求根 int flag = mid.find(Root); //在中序中查找根 front_mid_to_behind (front.substr(1 , flag) /*<---Tips1*/ , mid.substr(0 , flag) /*<---Tips2*/); //递归左子树 /*Tips1:front.substr(1 , flag) 一定要写1!!!因为先序第一个就是根,要去掉!!!*//*Tips2:mid.substr(0 , flag) 就只要写0,因为它的根在中间*/front_mid_to_behind (front.substr(flag + 1 , front.size() - flag - 1 /*<---Tips3*/) , mid.substr(flag + 1)); //递归右子树/*Tips3:(front.size() - flag - 1)一定不要写成flag!!! 有的样例只是巧合!!!(血淋淋的教训......)*/cout << Root; //输出根 }
}
void behind_mid_to_front (string mid , string behind) { //后中求先,同上if (mid.size() > 0) {char Root = behind[behind.size() - 1];cout << Root;int flag = mid.find(Root);behind_mid_to_front (mid.substr(0 , flag) , behind.substr(0 , flag));behind_mid_to_front (mid.substr(flag + 1) , behind.substr(flag , mid.size() - flag - 1));}
}

由于本人太屑,先后求中多情况的就不写了


五、树的应用

一、二叉堆写出优先队列

其实,优先队列好像可能大概八成使用二叉树实现的。优先队列,每个子树上根都最小(或者大)。
图:
接下来,介绍它如何插入一个元素:
当插入一个数时,优先队列会自动把它放到二叉树的最后一个位置。接着,那个数据会一层层比较,如果比子树的根小(或大),就把那个子树的根和数据对调,直到比某个子树的根小为止。

听不懂莫得关系,我有图!(虽然很丑)
原本的子树:

插入2后:

第一次交换:
现在,2比0小,就不交换了。

然后,介绍优先队列的删除。
当优先队列删除元素时,会删除根上的元素。但这么干,根就空了下来。最简单的做法,就是用二叉堆的最后一个元素去填补堆顶的元素,直到二叉树是合法的为止。


了解完优先队列,我们步入正题。用二叉树,可以模拟插入和删除。
贴C++源码:

template<class T>
void PriorityQueue<T>::Push(T key)
{if (Empty()){data[++size] = key;return;}int i;if (Full()){perror("Priority queue is full\n");return;}for (i = ++size; data[i / 2] > key; i /= 2)data[i] = data[i / 2];data[i] = key;
}template<class T>
void PriorityQueue<T>::Pop()
{int i, child;T min, last;if (Empty()){perror("Empty queue\n");return;}min = data[1];last = data[size--];for (i = 1; i * 2 <= size; i = child){child = i * 2;if (child != size && data[child + 1] < data[child])child++;if (last > data[child])data[i] = data[child];elsebreak;}data[i] = last;
}

各位大佬,有错请指出!!!

树学习笔记(以后会填坑)相关推荐

  1. 算法 | 虚树学习笔记

    虚树学习笔记? blog 虚树是一棵虚拟构建的树-废话 这棵树只包含关键点和关键的点,而其他不影响虚树结构的点和边都相当于进行了路径压缩-而且整棵虚树的大小不会超过关键点的2倍 举个例子? 比方说-4 ...

  2. 2019/12/25 学习总结(待填坑)

    今天发现了自己好多的知识盲区--待填坑-- CRF 参考博客:https://medium.com/ml2vec/overview-of-conditional-random-fields-68a2a ...

  3. 行列式、LGV、矩阵树学习笔记

    前置知识:矩阵.高斯消元 行列式 行列式定义 \[\text{det(A)}=\sum_{p}{(-1)^{\mathrm{sgn}(p)}\prod{A_{i,p_i}}} \] 其中 \(\tex ...

  4. 可持久化线段树学习笔记

    可持久化线段树,即主席树. 每次修改的时候不修改原来的节点,暴力建新节点,充分运用了函数式编程的思想. 模板题:给定一个数列,\(m\) 次询问求区间 \([l,r]\) 内的第 \(k\) 大. 利 ...

  5. 仙人掌圆方树学习笔记

    终于对仙人掌有了一点初步的理解. 仙人掌 仙人掌是什么? 仙人掌是一个无向图. 仙人掌有什么特点? 仙人掌的每条边只属于一个简单环. 下面是一个栗子 有什么用呢? 我们可以先用\(tarjan\)找出 ...

  6. bootstrap树节点如何设置默认不展开_GraPhlAn:最美进化树或层级分类树学习笔记

    Graphlan可视化进化树 撰文:文涛 南京农业的大学 责编:刘永鑫 中科院遗传发育所 GraPhlAn简介 总体来讲,Graphlan是一个可视化进化树和基于分类等级绘制层级分类树的工具.可以制作 ...

  7. 虚树学习笔记(洛谷2495 消耗战)

    题目链接 因为辣鸡csdn,导致之前快写好的博客没了 QWQ悲伤逆流成河qwqqq 首先虚树,这个东西,我感觉是一种思想,或者是方法,而并不是一个数据结构什么的. 他主要是用来解决:给出一棵树,每次询 ...

  8. DirectX11学习笔记十 imGUI入坑

    下载地址   Immediate Mode Graphical User interface,Immediate模式,不保存UI对象,用静态方法每帧创建,Unity里的GUI就是这种模式,适合小游戏或 ...

  9. 【爬虫】beautiful soup笔记(待填坑)

    Beautiful Soup是一个第三方的网页解析的模块.其遵循的接口为Document Tree,将网页解析成为一个树形结构. 其使用步骤如下: 1.创建对象:根据网页的文档字符串 2.搜索节点:名 ...

最新文章

  1. SparkR对R的支持情况
  2. 并发编程之对象的发布和逸出
  3. python引用大数据,Python 3 UDF
  4. BAT 批处理命令 - 文件批量复制、克隆功能实例演示
  5. go中如何使用easyjson_如何在 Go 中编写无 Bug 的 Goroutines?
  6. IM的扫码登录功能如何实现?一文搞懂主流的扫码登录技术原理
  7. Kafka学习笔记-Java简单操作
  8. 字串变换(洛谷-P1032)
  9. 自编码器(Auto-encoder) (下)它的应用
  10. mysql status uptime_MySQL优化(四) 慢查询的定位及优化
  11. 发送需要smtp认证的邮件
  12. android截屏与截长图截屏功能的实现
  13. Windows批量快速删除大量文件
  14. matlab 3维平滑,matlab 曲面平滑
  15. 【Enhanced Time-Frequency Representation and Mode Decomposition】翻译1
  16. 论文作业(2):Lossless Audio Coding 算法比较
  17. C语言中运算符的优先级排序表
  18. VS2019 MFC ODBC 操作SQL SERVER 数据库
  19. 图说区块链 神一样的金融科技与未来社会
  20. 什么是成本:(一)支出、费用及成本的关系

热门文章

  1. 笨方法学python3 ex20
  2. 什么东西可以改善睡眠质量?最好的助眠神器推荐
  3. Android使用本地Service实现后台播放音乐
  4. EasyAR_遇到的各种问题
  5. 算法训练 加法运算(你的表妹正在学习整数的加法,请编写一个程序来帮助她学习。该程序调用了一个函数GetTwoInts,由它来返回两个从键盘读入的100以内的整数,然后计算这两个整数之和,并把答案显示)
  6. MATLAB实现简单目标跟踪
  7. Win11系统安装NET3.5失败解决方案
  8. 机器学习中牛顿法凸优化的通俗解释
  9. 在线教育社区:怎样搭建网络学习空间
  10. 触摸屏幕时间长短时间、禁止页面点击事件