1. BST树
搜索树
保证左孩子小于根,右孩子大于根
为了保证树的查找效率不会退化成O(n),又在搜索树的基础上引入了平衡的概念。
二叉平衡搜索树:AVL、红黑树
多叉平衡搜索树:B-、B+、B*树
2. AVL树
二叉搜索树+平衡因子
左结点小于根,右节点大于根
左右孩子的高度差不超过1
其下面任意一棵树都是平衡树
高度:logn(允许是一颗空树)
这就导致插入的时候不仅仅要找到合适的位置,还要维护父节点的平衡因子。
插入
平衡因子{0,-1,1}(按右-左)
所以平衡因子要维护的情况一定是-2和2的情况
1.新节点插入后第一次检测
-1 -> 0 新结点在右侧插入,平衡因子变为0
1 -> 0 新结点在左侧插入,平衡因子变为0
0 -> -1/1 任意插入,父节点的高度增加了一层
2.旋转
- 左单旋:(右右失衡)新节点插入到较高右子树的右侧的情况。
- 右单旋:(左左失衡)新节点插入到较高左子树的左侧的情况。
- 右单旋、左单旋:(右左失衡)根节点和右子树的符号不一致,先把右子树右单旋(创造左旋的场景)、再把整棵树左单旋。
- 左单旋、右单旋:(左右失衡)根节点和左子树的符号不一致,先把左子树左单旋、再把整棵树右单旋。
3. 红黑树
是一个二叉搜索树+颜色控制平衡
满足如下性质:
左结点小于根,右节点大于根
结点只有红、黑两种
根节点必须是黑色
红节点的孩子必须是黑色
一个结点的每条路径中黑色结点是一样多的!!
NIL(空指针域)结点必须是黑色
- 红黑树中最长路径的个数 <= 2*最短路径的
- 操作一个结点最多只用三次旋转
- 不是绝对的平衡,是接近平衡的
-
为什么这些性质可以保证红黑树中最长路径的个数 <= 2*最短路径的个数?
因为红黑树必须保证同一个结点的每条路上的黑结点个数相同,所以根是黑色的话,第二层一定都是红色。
黑
/ \
黑 空
这就不对了,所以第二层一定是红色,那第三层一定就是黑色……
一个极端的例子:最长路径是黑-红-黑,最短路径是黑-黑
是满足性质的(但是建不起来这个树),这还不到2倍。
所以说按照性质正常建树一定是可以保证2倍这个特点的。 -
为什么黑色的头节点上一定要有header结点?
header里面存放的是end()迭代器的位置,指向最后一个元素的下一个位置。
减减end就可以访问到最后一个元素。
插入
默认插入都是红色,黑色是不符合规则后才调整成黑色。
情况1
插入结点为红,父节点为红,祖父结点为黑,叔叔结点存在且为红
解决:自己不变,将祖父改为红,父亲和叔叔改为黑,然后把祖父当作当前节点继续向上判断
情况2
自己是红,父亲为红,祖父为黑,叔叔不存在/为黑
解决:双亲和祖父结点交换颜色,祖父树右单旋。
红黑树和AVL树的区别
AVL | 红黑树 | |
---|---|---|
搜索效率 | 高 | 高 |
平衡 | 高度平衡 | 程度更轻 |
插入操作 | 调整频率高 | 调整频率更低 |
高度 | h=logn | h <= 2log(n+1) |
4. B树
要求M阶B树的每个结点最少有[M/2]-1个结点,最多有M-1个结点。
比如4阶B树的范围就是[1,3],一超过3那就要分裂
哈希表和搜索树的区别
哈希表 | 搜索树 | |
---|---|---|
时间复杂度 | O(1) | >O(1) |
特点 | 数组+链表 | 中序有序 |
应用 | hashMap、hashSet等 | 索引、TreeMap等 |
冲突 | 哈希冲突 | 不存在 |
查找 | 索引查找 | 范围查找 |