1、二叉查找树
二叉查找树 BST(binary search/sort tree)又叫二叉搜索树或者二叉排序树,它首先是一个二叉树,而且必须满足下面的条件:
1)若左子树不空,则左子树上所有结点的值均小于它的根节点的值(左小)
2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值(右大)
3)左、右子树也分别为二叉排序树
2、平衡二叉树
平衡二叉树(AVL树),又称自平衡二叉查找树。平衡二叉树必定是二叉搜索树,反之则不一定。满足下面的条件:
1、左结点小于根节点,右结点大于根节点
2、左子树和右子树的高度差不得超过1。这里通过平衡因子记录左右子树的高度差。平衡因子:左子树的高度减去右子树的高度。由平衡二叉树的定义可知,平衡因子的取值只可能为0,1,-1.分别对应着左右子树等高,左子树比较高,右子树比较高。
AVL树失衡旋转调整过程
AVL树的查找稳定,查找、插入、删除的时间复杂度都为O(logN),但是由于要维持自身的平衡,所以进行插入和删除结点操作的时候,需要对结点进行频繁的旋转。
AVL树的失衡调整主要是通过旋转最小失衡子树来实现的。最小失衡子树:在新插入的结点向上查找,以第一个平衡因子的绝对值超过1的结点为根的子树称为最小不平衡子树。只要调整最小不平衡子树,就能够将不平衡的树调整为平衡树。
还有一种情况:通过旋转后仍然不平衡
这种情况属于LR型
第一个字母表示最小不平衡子树根结点的平衡因子,第二个字母表示最小不平衡子树较高子树的根结点的平衡因子。使用L表示左子树较高,R表示右子树较高,E表示左右子树等高。
当然还有其他情况:LL型、LE型、RR型、RL型、RE型...
B树的引出:
AVL树每一个节点只能存放一个元素,并且每个节点只有两个子节点。当进行查找时就需要多次磁盘IO(数据是存放在磁盘中的,每次查询是将磁盘中的一页数据加入内存,树的每一层节点存放在一页中,不同层数据存放在不同页)这样如果需要多层查询就需要多次磁盘IO。为了解决AVL树的这个问题,就出现了B树。
我们为了减少磁盘IO的次数,就必须降低树的深度,将“瘦高”的树变得“矮胖”。一个基本的想法就是:
(1)、每个节点存储多个元素
(2)、摒弃二叉树结构,采用多叉树
这样就引出来了一个新的查找树结构 ——多路查找树。 根据AVL给我们的启发,一颗平衡多路查找树(B~树)自然可以使得数据的查找效率保证在O(logN)这样的对数级别上。
3、B树
B树(Blance-Tree)平衡树,也叫作B-树。一个m阶的B树规定了:
1.根结点至少有两个子女。
2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m 。
3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m。
4.所有的叶子结点都位于同一层。
5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。
时刻保证:左子小于根节点小于右子
查找节点8时,在二叉搜索树中4次IO操作,B树只用了3次。虽然B树节点所含的元素多不过只是多了几次内存交互而已。
B树的特点:树的高度越低,IO操作足够少,内存交互可以忽略,查找性能越好。
B树插入和删除元素
时刻保证:左子小于根节点小于右子这个规则旋转
B树主要用于数据库索引(非关系型MongoDB),文件系统等。
4、B+树
在B树基础上的优化,查找性能更好。一个m阶的B+树具有如下几个特征:
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。
B+树的优势:
1.单一节点存储更多的元素,使得查询的IO次数更少。
2.所有查询都要查找到叶子节点,查询性能稳定。
3.所有叶子节点形成有序链表,便于范围查询。
5、红黑树
红黑树(RB-Tree)是一种自平衡的二叉查找树,它的节点的颜色为红色和黑色。它不严格控制左、右子树高度或节点数之差小于等于1。也是一种解决二叉查找树极端情况的数据结构。红黑树的特性:
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。也就是说从每个叶子到根的所有路径上不能有两个连续的红色节点。
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
红黑树能够以O(logN)的时间复杂度进行搜索、插入、删除操作。红黑树在查找方面和AVL树操作几乎相同。但是在插入和删除操作上,AVL树每次插入删除会进行大量的平衡度计算,红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,结合变色,降低了对旋转的要求,从而提高了性能。任何不平衡都会在三次旋转之内解决。
红黑树广泛用于TreeMap、TreeSet,以及JDK1.8的HashMap。