红黑树的性质不在多说,百度都有,今天来说说红黑的插入
红黑的插入分为三种情况,将其画了出来
这是第一种情况:
这是第二种情况
第三种情况为
代码里有注释
enum Color{
BLACK, RED
}
class RBNode<T extends Comparable<T>>{//创建红黑树的节点 值域、左孩子、右孩子、父亲,颜色
private T data;
private RBNode<T> left;
private RBNode<T> right;
private RBNode<T> parent;
private Color color;
// 构造函数
public RBNode(T data, RBNode<T> left, RBNode<T> right, RBNode<T> parent, Color color) {
this.data = data;
this.left = left;
this.right = right;
this.parent = parent;
this.color = color;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public RBNode<T> getLeft() {
return left;
}
public void setLeft(RBNode<T> left) {
this.left = left;
}
public RBNode<T> getRight() {
return right;
}
public void setRight(RBNode<T> right) {
this.right = right;
}
public RBNode<T> getParent() {
return parent;
}
public void setParent(RBNode<T> parent) {
this.parent = parent;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
class RBTree<T extends Comparable<T>>{//创建红黑树
private RBNode<T> root;//红黑树的根节点
public RBTree() {
this.root = null;
}
/**
* 红黑树的插入
* @param data
*/
public void insert(T data){
if (this.root == null){//如果这个红黑树上,没有节点就new一个新节点
this.root = new RBNode<>(data,null,null,null,Color.BLACK);
return;
}
RBNode<T> cur = this.root;//将根节点的地址给新创建的cur
RBNode<T> parent = null;// 设置这节点的父节点
// 找节点插入的位置和BST树的查找插入位置一样
while (cur != null){
if (cur.getData().compareTo(data)>0){
parent = cur;
cur = cur.getLeft();
}else if (cur.getData().compareTo(data)<0){
parent = cur;
cur = cur.getRight();
}else {
return;
}
}
// 红黑树的插入节点是红色
RBNode<T> node = new RBNode<>(data,null,null,parent,Color.RED);
if (parent.getData().compareTo(data)>0){
parent.setLeft(node);//将此节点设置为父亲节点左边
}else {
parent.setRight(node);//将此节点设置为父亲节点的右边
}
if (color(parent(node)) == Color.RED){//如果插入的这个节点的父亲节点为红色 进入下面的颜色调整函数
fixAfterInsert(node);
}
}
/**
* 颜色调整函数
* @param node
*/
private void fixAfterInsert(RBNode<T> node) {
while(color(parent(node)) == Color.RED){//当插入的这个节点的父亲节点为红色进入这个循环
if(left(parent(parent(node))) == parent(node)){
// 当前节点,父节点在祖先节点的左子树
RBNode<T> uncle = right(parent(parent(node)));//设置一个叔叔节点
if(color(uncle) == Color.RED){ // 叔叔节点为红色 插入情况1
setColor(parent(node), Color.BLACK);//设置其节点的父亲节点为黑色
setColor(uncle, Color.BLACK);//设置其叔叔的节点为黑色
setColor(parent(parent(node)), Color.RED);//设置父亲的父亲为红色
node = parent(parent(node));//将node指向父亲的父亲
} else {//叔叔节点不为红色 并且要插入的节点node在右子树上
if(node == right(parent(node))){ // 插入情况3前半段
node = parent(node);//设置要旋转的节点为node的父亲节点
leftRotate(node);//进行左旋
}
// 插入情况3后半段和情况2合并
setColor(parent(node), Color.BLACK);//设置节点的父亲节点为父亲节点
setColor(parent(parent(node)), Color.RED);//设置此节点的父亲的父亲为红色,进行右旋
rightRotate(parent(parent(node)));
break;
}
} else {
// 当前节点,父节点在祖先节点的右树 和上面的一模一样
RBNode<T> uncle = left(parent(parent(node)));
if(color(uncle) == Color.RED){ // 插入情况1
setColor(parent(node), Color.BLACK);
setColor(uncle, Color.BLACK);
setColor(parent(parent(node)), Color.RED);
node = parent(parent(node));
} else {
if(node == left(parent(node))){ // 插入情况3前半段
node = parent(node);
rightRotate(node);
}
setColor(parent(node), Color.BLACK); // 插入情况3后半段和情况2合并
setColor(parent(parent(node)), Color.RED);
leftRotate(parent(parent(node)));
break;
}
}
}
// 有可能向上回溯到根节点跳出,把根节点置成黑色
setColor(this.root, Color.BLACK);
}
//左旋 这个旋转是基于BST树的旋转 这个要设置它的父亲和孩子进行绑定
private void leftRotate(RBNode<T> node){
RBNode<T> child = node.getRight();
child.setParent(node.getParent());
if(node.getParent() == null){
this.root = child;
} else {
if(node.getParent().getLeft() == node){
node.getParent().setLeft(child);
} else {
node.getParent().setRight(child);
}
}
node.setRight(child.getLeft());
if(child.getLeft() != null){
child.getLeft().setParent(node);
}
child.setLeft(node);
node.setParent(child);
}
//右旋
private void rightRotate(RBNode<T> node){
RBNode<T> child = node.getLeft();//定义要旋转的节点的左孩子
child.setParent(node.getParent());//设置孩子的父亲
if (node.getParent()==null){//如果要旋转的节点的父为null
this.root = child;//将系统认定的根节点拉到child上
}else {//判断要旋转的节点为他父节点的左边,设置为左边,或者设置为又变了
if (node.getParent().getLeft()==node){
node.getParent().setLeft(node);
}else {
node.getParent().setRight(node);
}
}
node.setLeft(child.getRight());//将要旋转的节点的左边设置为孩子节点右节点
if (child.getRight()!=null){//孩子的右孩子不为空,设置为它父节点
child.getRight().setParent(node);
}
//将要旋转的节点设置为孩子节点的右孩子
child.setRight(node);
node.setParent(child);//设置要旋转的父亲为child
}
private Color color(RBNode<T> node){
return node == null ? Color.BLACK : node.getColor();
}
public void setColor(RBNode<T> node, Color color){
node.setColor(color);
}
public RBNode<T> left(RBNode<T> node){
return node.getLeft();
}
public RBNode<T> right(RBNode<T> node){
return node.getRight();
}
public RBNode<T> parent(RBNode<T> node){
return node.getParent();
}
}