红黑树
二叉排序树:左孩子节点比父节点小,右孩子节点比父节点大,并且左右子树都是二叉排序树。
二叉排序树缺陷:在极端情况下,比如插入的序列是有序的,那么二叉排序树就会退化成单支树(链表)。
解决方案:优化成平衡树(AVL树,红黑树),在插入的同时调整这棵树,让节点分布尽可能地均匀。之所以要平衡,是因为树的查找性能取决于树的高度,而平衡树就是在降低树的高度。
B树
B树是一种多路搜索树,它的每个节点可以拥有多于两个孩子节点。M路的B树最多可以拥有M个孩子节点。
比如:(三路B树)
B树设计成多路的原因也是为了进一步降低树的高度。但是路的数目是有限的,为什么不能是无限的呢?
如果B树的路数是无限的,那么B数就会退化成一个有序数组:
这样会有什么问题?
我们知道,B树通常用于做文件系统的索引,而文件系统和数据库的索引都是存在硬盘上的,并且如果数据量大的话,不一定能一次性加载到内存中。显然,对于这种线性的结构,这种情况下就无法进行有效查找了。
而B树的多路存储就可以解决这种问题,每次加载B树的一个节点,然后一步步往下找就可以了。而红黑树的节点只有一个数据,相对应的树就比存储同样数据量的B树高很多,如果也采用这种查找方法,就需要多次磁盘IO,性能就会大大降低,所以一般文件系统的索引就不会采用红黑树,当然更不会采用有序数组。
B+树
B+树是在B树的基础上进行改造,它的数据都在叶子节点上,同时叶子节点之间还加了指针形成链表。
例如:(4路B+树)
B+树之所以这样设计,是因为B+树主要应用于数据库的索引,而数据库有一个主要业务是:select。比如:
select * from table_name where id between 7 and 17;
上面这条SQL语句是选取 table_name 表中 id 在7到17之间的数据。
如果是底层的结构是B树,那么需要做局部的中序遍历,可能还会涉及到跨层访问。而B+树由于所有数据都在叶子结点,不用跨层,同时由于有链表结构,只需要找到首尾,通过链表就能把所有数据取出来了。
注:MySQL不同的数据引擎底层设计有一些区别:MyISAM是在叶子节点存储一个指针,指向你所要查找的数据,而InnoDB是直接存储在叶子节点的(也就是说索引和你要查的数据在一块)