左倾红黑树——左倾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)的时间复杂度进行增.删.改.查,从存储 ...
随机推荐
- sqlserver 远程链接
远程链接的文档就不说了,网上好多. 这里就说下我遇到的情况,如果是阿里云的服务器的话,他的端口配置都是要到阿里云里的安全组里去配置的,第一次一直没想到,搞了一天才发现,在这里提醒各位好友.
- 【知识点】SPU&SKU
SPU:标准化产品单元 SPU = Standard Product Unit (标准化产品单元),SPU是商品信息聚合的最小单位,是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的特性. ...
- mysql单个表拆分成多个表
一.横向拆分 create table 新表的名称 select * from 被拆分的表 order by id limit int1,int2 int1为其实位置,int2为几条 注意:这样拆分后 ...
- Linux进程管理之top
关于Linux进程查看,前面讲解了ps命令,下面拉介绍另一个命令top ps:静态查看 top:动态查看 动态查看进程的状态 # top [root@wei ~]# top top - 18:38:4 ...
- 设置进程的cpu亲和性
在busybox中提供了一个名叫taskset的命令用于设置进程的cpu亲和性,让指定的进程或者程序在指定的cpu上面运行,该程序是通过调用sched_getaffinity和sched_setaff ...
- ubuntu无法连接网络
一,先说一下VMware软件和linux镜像的版本: VMware Workstation 14 Pro ubuntu-14.04.6-desktop-amd64.iso 二,遇到的问题 在第一次安装 ...
- 性能测试基础---jmeter二次开发
·Jmeter的二次开发,常见的有以下几种类型: ·扩展.修改Jmeter已有的组件(源代码) ·扩展.修改Jmeter已有的函数. ·完全自主开发一个新的组件(依赖于Jmeter提供的框架). ·扩 ...
- Springboot测试类之@RunWith注解
@runWith注解作用: --@RunWith就是一个运行器 --@RunWith(JUnit4.class)就是指用JUnit4来运行 --@RunWith(SpringJUnit4ClassRu ...
- Git的小疑惑
①怎么理解Git clone ssh://...git 和 Git remote add [shortname] [url]:Git fetch [shorename];的区别:为什么已经把远 ...
- python gevent协程
安装 pip install gevent import gevent from gevent import monkey monkey.patch_all()#捕捉所有阻塞,不止接收gevent.s ...