1.考考你
到目前为止,我们已经知道了树的基本概念,树的存储方式,以及树的前、中、后序遍历。接下来我们一起分享常见的一些树,主要从定义及用途上来分享,算是科普。
如果你对树已经有很深入的研究,那么可以考虑略过;反过来还是值得你看一看。那么都有哪些常见的树呢?我们先列举一下:
-
满二叉树
-
完全二叉树
-
二叉查找(搜索)树
-
红黑树
-
堆树
#考考你:
1.你知道常见的树都有哪些吗
2.你知道每一种树的特点吗
2.案例
2.1.满二叉树
#满二叉树定义:
1.叶子节点都在最底层
2.除了叶子节点,每个节点都有左、由两个子节点
#特点:
1.满二叉树,是一棵特殊的完全二叉树
2.关于完全二叉树,参考:2.2
2.2.完全二叉树
#完全二叉树定义:
1.叶子节点都在最底下两层
2.最后一层的子节点,都靠左排列
3.除了最后一层,其它层的节点个数,都要达到最大
#特点:
1.可以通过数组实现顺序存储
2.从下标1存储根节点开始:
i存储父节点
2*i存储左子节点
2*i+1存储右子节点
3.每个节点省去链表存储法中的左、右两个子节点指针,有效节省了存储空间
2.3.二叉查找树
#二叉查找树定义:
1.树中的每一个节点的值
2.都要大于左子树中每个节点的值
3.都要小于右子树中每个节点的值
#特点:
1.二叉查找树是最常用的一种二叉树,原因:
1.1.通过中序遍历二叉查找树,可以实现顺序访问二叉树每一个节点
1.2.支持快速插入、删除、查找操作,理想情况下时间复杂度是:O(logn)
2.与散列表对比:
2.1.二叉查找树,支持动态数据集合的快速插入、删除、查找操作,时间复杂度:O(logn)
2.2.你还记得散列表吗?散列表也支持动态数据集合的快速插入、删除、查找操作,时间复杂度:O(1)
2.3.疑问:既生瑜(常量级的散列表)、何生亮(对数级的二叉查找树)
2.4.可能的原因:
a.散列表中存储的数据是无序的,不能实现顺序访问
b.二叉查找树,通过中序遍历即可实现顺序访问
c.散列表构造实现复杂,需要考虑:散列函数设计、散列冲突解决、扩容、缩容
d.二叉查找数构造实现相对简单
2.5.在实际应用中,我们需要根据业务需求选择:散列表、或者二叉查找树。它们的同时存在并不冲突,不是非瑜即亮的问题
2.4.红黑树
#红黑树定义:
1.红黑树是一棵二叉查找树
2.红黑树是一棵【近似平衡】的二叉查找树
3.【平衡】的意思是指:任意一个节点,它的左、右子树的高度相差,不能大于1
4.疑问:为什么需要平衡二叉查找树呢
5.可能的原因:
a.二叉查找树支持快速的插入、删除、查找操作,时间复杂度:O(logn)
b.但是二叉查找树在动态插入、删除操作中,可能会退化,极端情况下会退化成链表
c.这个时候时间复杂度是:O(n)
d.为了避免二叉查找树退化,需要维护它的平衡性,保证操作效率
#特点:
1.如何构造一棵红黑树呢?
2.红黑树满足:
a.根节点是黑色的节点
b.叶子节点不存储数据,都是黑色的空节点
c.红色的节点不能相邻,必须被黑色节点隔开
d.每个节点,从该节点到达可达叶子节点的所有路径上,黑色节点数目相同
c.jdk8中HashMap、ConcurrentHashMap在解决散列冲突的时候,使用了红黑树与链表结合。推荐你可以看一下源码
2.5.堆树
#堆的定义
1.堆居然也是一棵树,没错,它叫做堆树,通常用于堆排序
2.注意这里的堆,可不是jvm的堆内存,要区分开来。它们是两个不同的种族
3.堆的具体描述:
a.堆是一棵完全二叉树
b.堆中每一个节点的值,都必须大于等于(或者小于等于)左、右子树中的每个节点值
c.如果大于等于左、右子树节点值,叫做大顶堆
d.如果小于等于左、右子树节点值,叫做小顶堆
#特点
1.基于堆的定义描述
2.在实际软件开发中,堆可应用于:
a.实现优先级队列(事实上堆本身就是优先级队列)
b.求解TopN问题
c.求解中位数问题
来源:oschina
链接:https://my.oschina.net/u/4450329/blog/4311411