二叉排序树、平衡二叉树、B树&B+树、红黑树的设计动机、缺陷与应用场景
之前面试时曾被问到“如果实现操作系统的线程调度应该采用什么数据结构?”,因为我看过ucore的源码,知道ucore是采用斜堆的方式实现的,可以做到O(n)的插入、O(1)的查找。我回答了斜堆,但面试官坚持让我在B树和红黑树之间选择一个,由于实际上很少用到B树和红黑树,所以我也不太清楚,只是隐约记得红黑树用于磁盘读取比较好,好像和数据大小和数据连续性相关,显然我记错了。当时觉得红黑树还有一些应用,应该命中的可能性比较大,就随意答了红黑树。当然回答错啦,面试官还给我简单讲解了一下,一直想着有机会好好总结一下这几个树的设计动机、缺陷和应用场景。最近有些时间,决定好好复习一下,毕竟数据结构才是基础。
树
为什么要引入树呢?一般在学习数据结构时,往往先学习向量和列表,然后是栈与队列。事实上,栈与队列只是在组织数据时额外加入了一些限制,分别是先进后出和先进先出,向量和列表都可以实现这种策略。那么向量和列表又存在什么缺陷呢?一般来讲,我们需要对数据结构做静态操作和动态操作,静态操作就是查找,动态操作就是插入和删除。在C/C++中一般采用数组实现向量,采用链表实现列表。接下来我们看一下它们的静态和动态操作的时间开销。
| 向量 | 列表
- | :-: | -:
静态操作(查找) | O(1)| O(n)
动态操作(插入、删除) | O(n) | O(1)
可以看到,已有的数据结构不能很好的平衡静态操作和动态操作的时间开销。
二叉排序树、平衡二叉树
一种简单的方法是采用二叉排序树(也叫二叉搜索树,BST,Binary Search Tree),构造一颗二叉排序树十分简单。一般来讲,大于根节点的放在根节点的右子树上,小于根节点的放在根节点的左子树上(如果等于根节点,则可视情况而定),如果写程序的话,可以采用递归的方式,而且由于不存在重叠子问题的情况,因此递归的性能已经足够好(不考虑栈溢出的情况)。
二叉排序树在通常情况下可以达到O(lgN)的静态、动态操作的时间复杂度,但是存在一种特殊情况,即输入的数据本身就是有序的,这时二叉排序树退化成向量。
为了消除二叉排序树对于输入敏感的特性,引入平衡二叉树,事实上平衡二叉树应该叫平衡二叉排序树也许更合理。它采用递归的方式定义,这里我就不去查书上的标准定义了,只要保证每个节点左子树和右子树的高度差小于等于1就可以了。
平衡二叉树(也叫AVL树)就比较好用了,可以弥补二叉排序树对输入敏感的缺陷,可以确保静态和动态操作的时间复杂度为O(loN)。
B树&B+树
1981年,Bill Gates曾说过这样一段话“640KB is ought to be enough for anybody.”,可能当时intel生产的内存只有640KB,今天看来这句话也许很荒唐,目前好一点的机器都已经达到16GB的内存了,但是事实上这句话仍然有一定的道理。
只要学习过操作系统的人都知道,存储器的访问速度和容量往往成反比(这句话不是很妥当,只要领会意思就好),最快的当然是CPU上的寄存器,然后是cache(多级cache,不同硬件平台不同),然后是内存、外部硬盘等等。当两个处在不同层级上的存储器彼此之间交互数据时(例如内存与硬盘之间),我们称之为I/O,事实上这种I/O操作相当耗时,应该尽可能避免。
B树的出现就是为了解决这个问题,B树由于是多路二叉树,事实上它的高度要远低于二叉平衡树。一般来讲,我们可以认为二叉平衡树每下降一层需要执行一次磁盘I/O操作,以1G数据为例,平均需要30次磁盘I/O才能读取到数据,而B树每下降一层,每个超级结点都会读入多个关键码,需要的磁盘I/O次数小于AVL树,因此B树适用于实现磁盘的读写逻辑。
红黑树
对于向量、列表、树和图来说,它们每次的动态操作都会完全遗忘之前的状态,转而到达全新的状态,这种数据结构称为ephemeral structure。另一种数据结构可以记录某一历史时刻的状态,在访问时可以根据版本好+目标数据进行访问,这种数据结构称为persistent structure。事实上,红黑树可以实现这种对历史版本的记录,我也不懂它为什么有这么奇妙的功能,这里就不再深入研究了,因为我觉得研究明白以后我还是会忘,有机会再看。
结论
回到最初的问题,即面试官提到的问题。我觉得面试官强迫我在B树和红黑树之间选择没有多少道理,因此线程调度的数据量很小,不涉及磁盘I/O的问题,同时线程调度好像也没有记录历史版本的需求,而这两个数据结构的静态和动态操作的时间复杂度一样,空间复杂度也接近,因此它们两个应该差不多才对。话说,它们两个的实现效率都不如斜堆。
二叉排序树、平衡二叉树、B树&B+树、红黑树的设计动机、缺陷与应用场景的更多相关文章
- 1.红黑树和自平衡二叉(查找)树区别 2.红黑树与B树的区别
1.红黑树和自平衡二叉(查找)树区别 1.红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单. 2.平衡 ...
- 数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树
某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较为简单,容易教学.在这里,我们区分开左倾红黑树和普通红黑树. 红黑树 ...
- 从二叉搜索树到AVL树再到红黑树 B树
这几种树都属于数据结构中较为复杂的,在平时面试中,经常会问理解用法,但一般不会问具体的实现,所以今天来梳理一下这几种树之间的区别与联系,感谢知乎用户@Cailiang,这篇文章参考了他的专栏. 二叉查 ...
- 从二叉查找树到平衡树:avl, 2-3树,左倾红黑树(含实现代码),传统红黑树
参考:自平衡二叉查找树 ,红黑树, 算法:理解红黑树 (英文pdf:红黑树) 目录 自平衡二叉树介绍 avl树 2-3树 LLRBT(Left-leaning red-black tree左倾红黑树 ...
- 简述树,Trie,Avl,红黑树
树的表示方法 在平时工作中通常有2种方式来表示树状结构,分别是孩子链表示法和父节点表示法.光说名词可能无法让人联系到实际场景中,但是写出代码之后大家一定就明白了. 孩子链表示法,即将树中的每个结点的孩 ...
- 红黑树、B(+)树、跳表、AVL等数据结构,应用场景及分析,以及一些英文缩写
在网上学习了一些材料. 这一篇:https://www.zhihu.com/question/30527705 AVL树:最早的平衡二叉树之一.应用相对其他数据结构比较少.windows对进程地址空间 ...
- 大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转
前言 11.1新的一月加油!这个购物狂欢的季节,一看,已囊中羞涩!赶紧来恶补一下红黑树和2-3树吧!红黑树真的算是大名鼎鼎了吧?即使你不了解它,但一定听过吧?下面跟随我来揭开神秘的面纱吧! 一.2-3 ...
- 红黑树与AVL树
概述:本文从排序二叉树作为引子,讲解了红黑树,最后把红黑树和AVL树做了一个比较全面的对比. 1 排序二叉树 排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索. 排序二叉树 ...
- AVL树、splay树(伸展树)和红黑树比较
AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...
随机推荐
- Struts2中Action接收参数的方法主要有以下三种:
Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数(最原始的方式): a.定义:在Action类中定义属性,创建get和set方法: b.接 ...
- RequireJS(一)
RequireJS: RequireJS中文网:http://www.requirejs.cn/ 解决HTML引入大量js文件导致的问题: 首先是加载的时候,浏览器会停止网页渲染,加载文件越多,网页失 ...
- linux 磁盘加密和tpm搭配使用1
一.基本名称,容易混淆 1.dm-crypt是linux的2.6内核开始集成的一种磁盘加密功能.十几年来,连sche调度算法都被改了N次,但dm-crypt一直稳定在内核中,稳定性还是很好的. 2.c ...
- 使用vue 遇到的问题————— 解决手机实时显示项目
Vue项目文件组织架构: src文件夹存放源代码. Static文件夹存放第三方静态资源. git将项目上传github http://blog.csdn.net/laozitianxia/ ...
- window安装swagger editor
1.下载 nodejs,并安装 2. 下载swagger editor并安装 2.1 git clone https://github.com/swagger-api/swagger-editor.g ...
- PhpStudy 升级 MySQL 版本到5.7
1:备份当前数据库数据. 最好是导成 SQL 文件 2:备份 PhpStudy 下的 MySQL 文件夹.以防升级失败.还可以使用旧版本的数据库 3:下载MySQL5.7.解压.然后放在 PhpStu ...
- String.Format 格式化货币的小问题
今天在开发过程中,遇到一件让我觉得比较纳闷的事情:用String.Format 格式化充值金额的时候,我这样处理: String.Format("{0:C2}", dr[" ...
- cursor的moveToNext()与moveToFirst()
String sql = "select count(*) as c from sqlite_master where type ='table' and name ='" + t ...
- Struts2 (二)
1 自定义结果视图 1.1 自定义一个类实现com.opensymphony.xwork2.Result接口. package com.xuweiwei.action; import com.open ...
- CentOS 下开启PHP错误提示
我也是傻逼,一直在找图片无法上传的原因,这么久了才意识到自己没有在Linux系统的服务器下开启错误提示. 正文 默认模式下的apache是没有开启错误语法提示的,修改php.ini文件.不同的安装,p ...