左倾红黑树——左倾2-3树(不是jdk1.8的TreeMap的红黑树)



public class RBTree<K extends Comparable<K>, V> {
public static boolean RED = true;
public static boolean BLACK = false;
public Node root;
class Node {
K key;
V val;
Node left, right;
boolean color;
int size;//高度
Node(K key, V val, boolean color, int size) {
this.key = key;
this.val = val;
this.color = color;
this.size = size;
}
public String toString() {
return "(K:" + key + " V:" + val + " 色:" + (color==true?"红":"黑") + " s:" + size+ " 左:" + left + " 右:" + right +")";
}
}
public RBTree() {
}
public boolean isRed(Node x) {
if (null == x)
return false;//null是黑色
return x.color == RED;
}
public int size(Node x) {
if (x == null)
return 0;
return x.size;
}
public int size() {
return size(root);
}
public boolean isEmpty() {
return root == null;
}
public V get(K key) {
if (key == null)
throw new IllegalArgumentException();
return get(root, key);
}
public V get(Node n, K key) {
while (n != null) {
if (key.compareTo(n.key) == 0)
return n.val;
else if (key.compareTo(n.key) < 0)
n = n.left;
else
n = n.right;
}
return null;
}
private Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;//节点重挂
x.left = h;//旋转
x.color = x.left.color;
x.left.color = RED;
x.size = h.size;
h.size = size(h.left) + size(h.right) + 1;
return x;
}
private Node rotateRight(Node h) {//h.left和h.left.left是红色就右旋转h,
Node x = h.left;
h.left = x.right;//节点重挂
x.right = h;//旋转
x.color = x.right.color;
x.right.color = RED;
x.size = h.size;
h.size = size(h.left) + size(h.right) + 1;
return x;
}
private void flipColors(Node h) {// 颜色翻转
h.color = !h.color;
h.left.color = !h.left.color;
h.right.color = !h.right.color;
}
public void put(K key, V val) throws Exception {
if (key == null || val == null)
throw new Exception();
root = put(root, key, val);
root.color = BLACK;
}
//红黑树调整是从下到上,比较路上的所有节点,依次调整,不在比较路上的节点不用调整,调整时候看的也只是左右2个子节点。
private Node put(Node h, K key, V val) {//递归看形参,进去时候依次是5.0 4.0 3.0 2.0 1.0,出来时候是反过来的,依次是1.0搞完然后2.0搞完然后3.0搞完然后4.0然后5.0。
if (h == null)
return new Node(key, val, RED, 1);
int cmp = key.compareTo(h.key);// key < h.key
if (cmp < 0) {
// 放到h的左边,返回新的h的左边,因为有可能会翻转什么的,所以返回新的左节点。
h.left = put(h.left, key, val);
} else if (cmp > 0) {
// 放到h的右边,返回新的h的右边,
h.right = put(h.right, key, val);
} else {
h.val = val;
}
//每次给h增加左节点或者右节点之后,都要调整节点h。递归从下到上依次调整。
if (isRed(h.right) && !isRed(h.left))// h的右节点红色,左节点是null或者黑色。节点的右边不能是红色(性质)。
h = rotateLeft(h);
if (isRed(h.left) && isRed(h.left.left))
h = rotateRight(h);
if (isRed(h.left) && isRed(h.right))
flipColors(h);
h.size = size(h.left) + size(h.right) + 1;
return h;
}
public int getHeight() {
return getHeight(root);
}
private int getHeight(Node p) {// 递归:一个函数里面依赖包含另一个函数。
if (p == null)
return 0;
return Math.max(getHeight(p.left), getHeight(p.right)) + 1;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
RBTree rb = new RBTree();
rb.put(5.0, 5.00);
rb.put(4.0, 4.00);
rb.put(3.0, 3.00);
rb.put(3.5, 3.50);
rb.put(2.9, 2.90);
rb.put(3.6, 3.60);
rb.put(3.55, 3.550);
}
}
左倾红黑树的另一种定义是满足下列条件的二叉查找树:
- 红链接均为左链接。
- 没有两条红链接相连。
- 任意空链接到根结点的路径上的黑链接数量相同。








2-3树规定,2节点为黑色,3节点小红大黑,并且父节点链接的是大黑节点。小红在大黑的坐下,中间值节点在小红的右边。
2-3树规定了红黑树最终的样子和颜色,但是中间的旋转和变色过程 是通过2-3树的变换过程推到出来的,规则如下:

红黑树就是用红链接表示 3-结点的 2-3 树。
那么红黑树的插入、构造就可转化为 2-3 树的问题,即:在脑中用 2-3 树来操作,得到结果,再把结果中的 3-结点转化为红链接即可。
而 2-3 树的插入,前面已有详细图文,实际也很简单:有空则插,没空硬插,再分裂。 这样,我们就不用记那么复杂且让人头疼的红黑树插入旋转的各种情况了。只要清楚 2-3 树的插入方式即可。
2-3树:2个子节点或者3个子节点。
2-3树是平衡的3路查找树,其中2(2-node)是指拥有两个分支的节点,3(3-node)是指拥有三个分支的节点。B-树是一种平衡的多路查找树,2-3树属于b-树,其也同样具有B-树的性质,如m阶B-树,节点至多有m个分支、m-1个关键字;内部节点的分支数至少为m/2取上限;所有叶节点都出现在同一层次上,并且不带任何信息(这是由构造树的逻辑决定的,实际上指向这些节点的引用为null)。
2-3查找树的定义如下:
1. 要么为空,要么:
2 对于2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点,左节点也是一个2-3节点,所有的值都比key要小,有节点也是一个2-3节点,所有的值比key要大。
1. 对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。左节点也是一个2-3节点,所有的值均比两个key中的最小的key还要小;中间节点也是一个2-3节点,中间节点的key值在两个跟节点key值之间;右节点也是一个2-3节点,节点的所有key值比两个key中的最大的key还要大。

3个子节点根节点就有2个元素,2个子节点根就有一个元素。
永远都是在叶节点处插入新节点,当3-node变为4-node时,需要拆分节点,此时树高就有可能增加。
删除节点比插入节点麻烦一些,先来看删除底部节点,在搜索过程中就需要对节点做相应的变化,以保证搜索路径上的都是3-node或临时的4-node,在删除当前节点T时,T一定是3-node或4-node,就可以安全删除了,删除之后树的变化规则与插入一致。删除其他节点可以转化为删除底部节点,只需要将删除元素与底部节点元素交换即可。
2-3树作为一种平衡查找树,查询效率比普通的二叉排序树要稳定许多,其操作逻辑也非常清晰。2-3树可以采用红黑树实现,使用二叉树结构从逻辑上模拟了2-3树,在插入删除节点时,又具有二叉平衡树的便利。
B-tree树即B树,B即Balanced,平衡的意思。因为B树的原英文名称为B-tree,
左倾红黑树——左倾2-3树(不是jdk1.8的TreeMap的红黑树)的更多相关文章
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- 2-3-4树(jdk8的TreeMap的红黑树)
2-3树:插入变成2个节点正常插,变成3个节点就要提升中间节点和分裂子节点,满足:要么没有子节点,要么2个子节点,要么3个子节点. 2-3-4树:插入变成2个不动,插入变成3个不动,插入变成4个提升原 ...
- B树,B+树,红黑树应用场景AVL树,红黑树,B树,B+树,Trie树
B B+运用在file system database这类持续存储结构,同样能保持lon(n)的插入与查询,也需要额外的平衡调节.像mysql的数据库定义是可以指定B+ 索引还是hash索引. C++ ...
- [BinaryTree] AVL树、红黑树、B/B+树和Trie树的比较
转自:AVL树.红黑树.B/B+树和Trie树的比较 AVL树 最早的平衡二叉树之一.AVL是一种高度平衡的二叉树,所以通常的结果是,维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应 ...
- 红黑树以及与AVL树的区别
http://blog.csdn.net/zwan0518/article/details/12219055 http://blog.csdn.net/v_july_v/article/details ...
- 吐血整理:二叉树、红黑树、B&B+树超齐全,快速搞定数据结构
前言 没有必要过度关注本文中二叉树的增删改导致的结构改变,规则操作什么的了解一下就好,看不下去就跳过,本文过多的XX树操作图片纯粹是为了作为规则记录,该文章主要目的是增强下个人对各种常用XX树的设计及 ...
- 为什么HashMap使用红黑树而不使用AVL树
为什么HashMap使用红黑树而不使用AVL树? 红黑树适用于大量插入和删除:因为它是非严格的平衡树:只要从根节点到叶子节点的最长路径不超过最短路径的2倍,就不用进行平衡调节 AVL 树是严格的平衡树 ...
- 【算法】通过TreeMap理解红黑树
本文以Java TreeMap为例,从源代码层面,结合详细的图解,剥茧抽丝地讲解红黑树(Red-Black tree)的插入,删除以及由此产生的调整过程. 总体介绍 Java TreeMap实现了So ...
- Java集合详解6:TreeMap和红黑树
Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储 ...
随机推荐
- ASP.NET MVC自定义Module记录管道事件执行顺序
1. 在Visual Studio 新建项目,模板为空,下面结构选择MVC. 2. 在项目中新建一个类MyModule,实现IHttpModule接口 namespace SimpleApp.Infr ...
- Qt keyevent学习笔记
在按下一个键不放后,会发生: 1.触发keypressevent(),此时isautorepeat()返回false: 2.set isautorepeat(),使其返回值为true; 3.触发key ...
- vue中路由拦截无限循环的情况
router.beforeEach(async (to, from, next) => { if (token) { if (whiteList.indexOf(to.path) != -1) ...
- QQ空间自动点赞js脚本
这是很久前写的脚本了,在浏览器打开QQ空间,并在控制台输入代码就可 时间间隔最好开大点,不然容易被暂时冻结账号 function autoLike() { var list=document.getE ...
- elasticsearch 安装 可视化工具
一.windows下安装Elasticsearch首先计算机需要JAVA环境(已有次此环境跳过)1.java环境安装网址:http://www.oracle.com/technetwork/java/ ...
- Vuex中mapState的用法
Vuex中mapState的用法 今天使用Vuex的时候遇到一个坑,也可以说是自己的无知吧,折腾了好久,终于发现自己代码的错误了.真是天雷滚滚~~~~~~ index.js import Vue ...
- xcode运行demo报错:Failed to create provisioning profile.cannot be registered to your development team
问题:网上下载运行demo,出现Failed to create provisioning profile.cannot be registered to your development team此 ...
- 《MySQL性能优化篇》阅读笔记
建表的时候,不要用null赋默认值,如:字符串的设置'',数据类型的设为0,不要将null设为默认值. 在MySQL中没有 full [outer] join,用union代替 各种 JOIN SQL ...
- Comet OJ 夏季欢乐赛 分配学号
Comet OJ 夏季欢乐赛 H 分配学号 题目传送门 题目描述 今天,是JWJU给同学们分配学号的一天!为了让大家尽可能的得到自己想要的学号,鸡尾酒让大家先从 [1,10^{18}][1,1018] ...
- 深度学习查看GPU实时使用情况
1.CPU使用情况查看 动态查看 打开终端,输入: $ top按Ctrl+C退出查看. 即可看到实时的CPU使用情况. 查看版本 $ top -h 即可看到当前procps-ng的版本. 2. gp ...