java学习记录-树结构
概念
树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。 树是由结点或顶点和边组成的(可能是非线性的)且不存在着任何环的一种数据结构。没有结点的树称为空(null或empty)树。一棵非空的树包括一个根结点,还(很可能)有多个附加结点,所有结点构成一个多级分层结构
结点:下面就是一个简单的树, 每一个元素都称为一个结点,而最顶端的是根结点,最末端的是叶子结点, 每个结点有零个或多个子结点;每一个非根结点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树
度:度就是一棵树里面最大的宽度,下图树(包含子树)的子结点数最大都不超过2所以该树的度为2
深度: 由根结点到叶子结点组成该树各结点的最大层次
二叉树
二叉树又分为二叉查找树、完全二叉树、满二叉树、平衡二叉树、红黑树、B树
为什么二叉树也还要区分那么多种类型?因为单种二叉树不能完全保证我们运行或储存效率,所以需要多种类型二叉树应对不同的使用场景
下面先看一下二叉查找树
录入的顺序 为 E-->F-->C-->B-->D-->A--G
二叉树与树的区别
1.树的度没有限制,二叉树的度最大为2
2.二叉树每个子树都是有序的,例如二叉树的左子树如果非空,左子树所以结点的值都小于根节点的值,如果右子树非空,则右子树所有结点的值都大于根结点的值(左小右大)
因为二叉树左小右大的特点,所以二叉查找树有个比较极端的情况
录入的顺序 为 A-->B-->C-->D-->E
从小到大的开始录入,大的永远在右边,就造成了右斜树,与链表(线性结构)一样这种树并不能保证我们的运行效率
平衡二叉树(AVL树)
平衡二叉树是基于二叉查找树优化而来的
录入顺序: A-->B-->C-->D-->E-->F
录入顺序与一般二叉树一样,都是从小到大开始录入,但是平衡二叉树每次插入数据会判断数据的大小,从而进行左右旋转,使得我们的数据分布均匀,保证了一定的运行效率
平衡二叉树与二叉查找树的区别主要体现在二叉查找树的根结点不能变,平衡二叉树为了保证根结点左右子树的层级差不超过1,所以会进行左右旋转操作,这个时候根结点就会发生改变
优点:因为左右子树结点数量相差较少,所以查询速度极快
缺点:插入数据时候因为旋转次数不确定,所以插速度会相对慢
红黑树
性质:
红黑树与平衡二叉树相似,平衡二叉树基于 根结点左右子树的层级差不超过1 进行旋转操作,而红黑树则是基于 没有任何一条路径比其他路径长两倍以上进行(旋转次数不超过3次,新增不超过2次,删除不超过3次)旋转
录入顺序: A-->B-->C-->D-->E-->F-->G
录入顺序: A-->B-->C-->D-->E-->F-->G-->H
由第一张红黑树图可以看出,红黑树的平衡度并没有AVL树平衡度那么严格(只保持黑结点平衡)由于旋转次数是保证在3以内的,所以插入或删除结点时候性能要比平衡二叉树好
B树 --- Balance-tree(平衡多路查找树)
下面是一棵三阶的B树
录入顺序: A-->B-->C-->D-->E-->F-->G-->H
阶:每个B树都有个指定的阶(M),阶决定了每个结点最多拥有多少个子结点,例如三阶B树每个结点最多只能拥有三个子结点
阶与度不一样,上图树的度为2,阶为3,但是阶决定度的最大值
关键字:例如每一个结点里面的值就是一个关键字,例如,该结点就有2个关键字,G和H
B树的性质
1.每个结点里面的关键字数量最多为M-1,根节点最少可以只有1个关键字,非根节点至少有M/2(上取整)个关键字。
2.每个结点至少有2个子结点,叶子结点除外
3.除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1
4.B树的叶子结点都是在同一层
例如现在要录入一个A-E的三阶B树
先录入A和B
接下来要录入C,因为根结点的关键字数量为1到M-1和每个结点至少有2个子结点,所以录入C的时候应该B作为根结点,A和C作为子结点
插入D
插入E
插入元素时,如果树结构不满足B树的性质时,就会进行合并或分裂
B树与二叉树的比较
下面使用元素相同的平衡二叉树(二叉树里面查询快)与B树的查询作比较
平衡二叉树查询 H
第一步
第二步
第三步
第四步
B树查询 H
第一步
第二步
第三步
第四步
虽然看上去都是需要四步才能完成H的查询,因为树结构是非线性的,每个结点的地址是不连续的,所以B树的第四步是在一块内存内比较,要比平衡二叉树的第四步重新寻找地址快很多,并且,如果数据是存放在磁盘而不是内存的时候,每次IO操作性能消耗非常大,且随着数据量增大,两者的性能差距更加明显
B+树
B+树与B树的区别在于B+树每一个元素都存在于叶子结点,非叶子结点仅仅提供索引操作,必须到叶子结点才会命中
这样保证了我们寻找任意一个元素时,所需要的时间都是一样的
并且叶子结点以链表形式连接,这样有利于遍历所有数据时候,只需要进行线性查询,而不用一层一层遍历
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
手把手使用Python教你破解谷歌(Google)人机验证码—下篇
/1 前言/ 昨天其实已经发布了上篇,但是忘记标注原创了,今天继续将其发布出来,与下篇一起给大家,这样大家就可以直接重头看到尾了。这篇文章主要是实战,实现谷歌人机破解具体过程。 /2 实现步骤/ 1、既来之则安之,选择了2captcha,就要看看人家的官网啦,如下图所示。 2、嗯...纯英文,我也看不懂..怎么办呢,别着急,我带你们一步一步分析主要功能。首先来登录账号,如下图所示。 3、登录完成后,会自动跳到主页,如下图所示。 上图中第一个红色圈起来的地方表示剩余多少钱,没有钱的话记得要氪金,否则是不能用滴,氪金过程这里就不多做解释了哈,问题不大 第二个红色圈起来的地方表示这是你的唯一key,每次请求要带上这个key的,所以要保管好 4、进入主题,研究文档。点击红色圈的地方,API,一般API都是文档,如下图所示。 5、En....什么玩意..完全看不懂,别慌,往下滑 滑到rates这个目录,我们知道,谷歌人机是ReCaptcha,但是三个呢,到底是哪个呢,我就来带大家看看。 6、首先点击ReCaptcha(oldmethod),这个是老的方法,咱也不知道唉,所以就先看看这个吧,从浅到...
- 下一篇
java源码学习---HashMap
开门见山,直接干 HashMap是java常用的一个集合,每个元素的key经过哈希算法后储存在链表或红黑树的一种键值对数据集合(JDK1.8) 从HashMap新增元素说起 map.put("key","value"); 这是我们日常向HashMap插入元素的其中一种方式,put(k,v)的源码 public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } put()会再调用一个putVal(),但是在这之前key会通过hash()计算出对应位置的值,真正的put操作,就是从这里开始 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = r...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Mario游戏-低调大师作品
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装