红黑树是一种二叉平衡查找树,每个结点上有一个存储位来表示结点的颜色,可以是RED或BLACK。红黑树具有以下性质:

(1) 每个结点是红色或是黑色

(2) 根结点是黑色的

(3) 如果一个结点是红色的,则它的两个儿子都是黑色的

(4) 对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点

通过红黑树的性质,可以保证所有基于红黑树的实现都能保证操作的运行时间为对数级别(范围查找除外。它所需的额外时间和返回的键的数量成正比)。

Java的TreeMap就是通过红黑树实现的。

红黑树的操作如果不画图很容易搞糊涂,下面通过图示来说明红黑树的插入操作。

插入一个红色的节点到红黑树中之后,会有6种情况:图示中N表示插入的节点,P表示父节点,U表示叔叔节点,G表示祖父节点,X表示当前操作节点

代码如下:

 public class RedBlackBST<Key extends Comparable<Key>, Value> {
private Node root;
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node{
private Key key; //键
private Value val; //值
private Node left, right, parent; //左右子树和父节点
private boolean color; //由其父节点指向它的链接的颜色 public Node(Key key, Value val,Node parent, boolean color){
this.key = key;
this.val = val;
this.color = color;
}
} public Value get(Key key){
Node x = root;
while(x!=null){
int cmp = key.compareTo(x.key);
if(cmp < 0 ) x = x.left;
else if(cmp > 0) x = x.right;
else return x.val;
}
return null;
} public void put(Key key, Value val){
if(root==null) { //如果是根节点,就将节点新建为黑色
root = new Node(key,val,null,BLACK);
return;
}
//寻找合适的插入位置
Node parent = null;
Node cur = root;
while(cur!=null) {
parent = cur;
if(key.compareTo(cur.key)>0) cur=cur.right;
else cur = cur.left;
}
Node n = new Node(key,val,parent,RED); //普通的新建节点为红色
//将新节点插入parent下
if(key.compareTo(parent.key) > 0) parent.right = n;
else parent.left = n;
//插入新节点后要调整树中部分节点的颜色和属性来保证红黑树的特征不被破坏
fixAfterInsertion(n);
}
private Node parentOf(Node x) {
return (x==null ? null : x.parent);
}
private boolean colorOf(Node x) {
return (x==null ? BLACK : x.color);
}
private Node leftOf(Node x) {
return (x==null ? null : x.left);
}
private Node rightOf(Node x) {
return(x==null ? null : x.right);
}
private void setColor(Node x, boolean color) {
if(x!=null)
x.color = color;
} private void fixAfterInsertion(Node x) {
while(x!=null && colorOf(parentOf(x)) == RED) {
Node grandPa = parentOf(parentOf(x));
Node parent = parentOf(x);
if(parent == leftOf(grandPa)) {//case 1 || case2 || case3
Node uncle = rightOf(grandPa);
if(colorOf(uncle) == RED) {//case1, uncle is red
setColor(parent,BLACK); //父节点置黑
setColor(uncle, BLACK); //叔叔节点置黑
setColor(grandPa,RED); //祖父节点置红
x = grandPa; //因为祖父节点由黑转红,故要重新调整父节点及其祖先的红黑属性
}else {//case2 || case3,uncle is black
if(x==rightOf(parent)) { //case2
x = parent;
rotateLeft(x);
}
//case3
setColor(parent,BLACK);
setColor(grandPa, RED);
rotateRight(grandPa);
} }else {//case4 || case 5 || case6
Node uncle = leftOf(grandPa);
if(colorOf(uncle) == RED) { //case4 || case5 || case6
setColor(parent,BLACK);
setColor(uncle, BLACK);
setColor(grandPa,RED);
x = grandPa;
}else{ //case5 || case6, uncle is black
if(x==leftOf(parent)) { //case5
x = parent;
rotateRight(x);
}
//case6
setColor(parent,BLACK);
setColor(grandPa, RED);
rotateLeft(grandPa);
}
}
}
}
private void rotateLeft(Node x) {
if(x==null) return;
Node y = x.right;
x.right = y.left;
if(y.left!=null)
y.left.parent = x;
y.left = x;
y.parent = x.parent;
if(x.parent == null) {
root = y;
}
else if(x.parent.left == x) {
x.parent.left = y;
}else {
x.parent.right = y;
}
x.parent = y;
}
private void rotateRight(Node x) {
if(x==null) return;
Node y = x.left;
x.left = y.right;
if(y.right != null)
y.right.parent = x;
y.right = x;
y.parent = x.parent;
if(x.parent == null) {
root = y;
}else if(x.parent.left==x) {
x.parent.left = y;
}else {
x.parent.right=y;
}
x.parent = y;
} }

上面的rotateLeft和rotateRight有必要画个图示:

红黑树插入操作原理及java实现的更多相关文章

  1. stl map底层之红黑树插入步骤详解与代码实现

    转载注明出处:http://blog.csdn.net/mxway/article/details/29216199 本篇文章并没有详细的讲解红黑树各方面的知识,只是以图形的方式对红黑树插入节点需要进 ...

  2. 红黑树深入剖析及Java实现

    红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小, ...

  3. 红黑树插入与删除完整代码(dart语言实现)

    之前分析了红黑树的删除,这里附上红黑树的完整版代码,包括查找.插入.删除等.删除后修复实现了两种算法,均比之前的更为简洁.一种是我自己的实现,代码非常简洁,行数更少:一种是Linux.Java等源码版 ...

  4. 红黑树深入剖析及Java实现(转自知乎美团点评技术团队)

    作者:美团点评技术团队 链接:https://zhuanlan.zhihu.com/p/24367771 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 红黑树是平衡 ...

  5. 红黑树插入操作---以JDK 源码为例

    红黑树遵循的条件: 1.根节点为黑色. 2.外部节点(叶子节点)为黑色. 3.红色节点的孩子节点为黑色.(由此,红色节点的父节点也必为黑色) 4.从根节点到任一外部节点的路径上,黑节点的数量相同. 节 ...

  6. jdk源码分析红黑树——插入篇

    红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...

  7. 红黑树(五)之 Java的实现

    概要 前面分别介绍红黑树的理论知识.红黑树的C语言和C++的实现.本章介绍红黑树的Java实现,若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章.还是那句老话,红黑树的C/C+ ...

  8. 基于Java实现红黑树的基本操作

    首先,在阅读文章之前,我希望读者对二叉树有一定的了解,因为红黑树的本质就是一颗二叉树.所以本篇博客中不在将二叉树的增删查的基本操作了,需要了解的同学可以到我之前写的一篇关于二叉树基本操作的博客:htt ...

  9. 死磕 java集合之TreeMap源码分析(一)- 内含红黑树分析全过程

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 TreeMap使用红黑树存储元素,可以保证元素按key值的大小进行遍历. 继承体系 Tr ...

随机推荐

  1. 如何在MONO 3D寻找最短路路径

    前段时间有个客户说他们想在我们的3D的机房中找从A点到B点的最短路径,然而在2D中确实有很多成熟的寻路算法,其中A*是最为常见的,而这个Demo也是用的A*算法,以下计算的是从左上角到右下角的最短路径 ...

  2. NAT、NAPT(PAT)的基本概念和工作原理及区别

    转自:http://blog.sina.com.cn/s/blog_5d302bd20100gprv.html 近年来,随着 Internet 的迅猛发展,连入 Internet 的主机数量成倍增长. ...

  3. [angular1.6]Error: "transition superseded" ui-router 在angular1.6 报错误问题解决

    在angular1.6版本里,使用ui-router如果报这个错误,可以将ui-router升级到最近版本即可.ui-router version v0.4.2

  4. fread快读+fwrite快速输出

    定义数组 char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf; 读入 #define getchar() (p1==p2&a ...

  5. 服务器做ssh免秘钥登陆

    集群内服务器做非root用户免秘钥登陆:1.node1新建用户abc1,制作公钥.私钥(一路回车键即可)ssh-keygen –t rsa将自动在/home/abc1/.ssh/目录下创建公私钥文件如 ...

  6. vue-cli中src/main.js 的作用

    // The Vue build version to load with the `import` command // (runtime-only or standalone) has been ...

  7. C,LINUX,数据结构部分

    1604期 第1期测试(面试精选:C,LINUX,数据结构部分) 本试卷从考试酷examcoo网站导出,文件格式为mht,请用WORD/WPS打开,并另存为doc/docx格式后再使用 试卷编号:24 ...

  8. 【Lqb T336】Cowboys

    [链接] 我是链接,点我呀:) [题意] 出现AB就要交换一下 给你结果序列 问你原序列有多少种可能 首尾可以交换. [题解] 设 dp[i][0]表示i和i-1不交换,达到前i个字符序列的状态的方案 ...

  9. Python学习笔记 (1)Hello World(环境搭建+输出Hello World!)

    随想 高考发挥失常.科三遇火车发挥失常,各种不顺……突然发现假期都快没了,才想起高考前想象的这个假期要做的一堆事,现在来多完成一件吧. 这几篇博客仅只是我的学习笔记,凑合看吧.我这个python小白看 ...

  10. HDU 1085 多重背包转化为0-1背包问题

    题目大意: 给定一堆1,2,5价值的硬币,给定三个数表示3种价值硬币的数量,任意取,找到一个最小的数无法取到 总价值为M = v[i]*w[i](0<=i<3) 那么在最坏情况下M个数都能 ...