代码放在文末
红黑树添加元素:保持根为黑色,左旋。
需要左旋的情况如下图所示:
如果先添加40,再添加30,则为左旋,无需操作。
如过先添加30,再添加40,需要左旋操作,保证红黑树为左旋红黑树。
下图为左旋和颜色变换的示意图(包括变换的代码)
红黑树添加元素:颜色反转。
先在40的左侧和右侧分别贴上30和50(节点默认颜色为红色,根节点默认黑色)。
由于红黑树本质上就是二三树,一个四节点转换为3个2节点
首先三个节点在红黑树中都为单独的黑色节点,同时又需要保证层数不变,因此根节点变为红色,而两个子节点为黑色。需要右旋的情况如下图所示:
// An highlighted block
import javax.swing.*;
import javax.xml.soap.Node;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author xxo
* @param <E>
*/
public class RBT<E extends Comparable<E>> {
//因为添加元素时要比较大小,所以使用了Comparable
private static final boolean RED = true;
private static final boolean BLACK = false;
public Node root; //根节点
private int size; //总共的数量
public int size() { return size; }
//添加节点,递归
public void addEle(E e){
root = addEle(root,e);//以该节点为根,添加红黑树的元素
root.color = BLACK; //始终保持新添加到的子树的根是黑色。
}
/**
* 将元素E添加到node为根的那个树上并且将新树的根返回
* @param node
* @param e
* @return
*
*/
private Node addEle(Node node,E e){ //添加元素e到以node为根的子树上
if (node == null){ //并且返回新的根节点
size++;
return new Node(e);
}
if (e.compareTo(node.e)<0){
node.left = addEle(node.left,e); //与根节点比较,比根节点小往左加,大往有加
}else{
node.right = addEle(node.right,e);
}
//左旋
if(isRed(node.right)&&!isRed(node.left)){
node = leftRotate(node);
}
//右旋
if (isRed(node.left)&&isRed(node.left.left)){
node = rightRoatate(node);
}
//颜色翻转
if (isRed(node.left)&&isRed(node.right)){
flipColors(node);
}
return node;
}
// node x
// / \ 左旋 / \
// T1 x ----------> node T3
// / \ / \
// T2 T3 T1 T2
private Node leftRotate(Node node) {
Node x = node.right;
node.right = x.left;
x.left = node;
x.color = node.color;
node.color = RED;
return x;
}
//颜色翻转
private void flipColors(Node node){
node.color = RED;
node.left.color = BLACK;
node.right.color = BLACK;
}
// node x
// / \ 右旋 / \
// x T2 ----------> y node
// / \ / \
// y T1 T1 T2
private Node rightRoatate(Node node){
Node x = node.left;
node.left = x.right;
x.right = node;
x.color = node.color;
node.color = RED;
return x;
}
private boolean isRed(Node node){
if(node==null)return BLACK;
return node.color;
}
private class Node{
public E e;
public Node left;
public Node right;
public boolean color;
public Node(E e){
this.e = e;
this.left = null;
this.right = null;
this.color = RED;
}
@Override
public String toString() {
return "Node{" +
"e=" + e +
", color=" + color +
'}';
}
}
/**
* 层次遍历树
*/
public void levelOrder(){
if(root==null){
return;
}
Queue<Node> queue = new LinkedList();
queue.add(root);
while(!queue.isEmpty()){
Node curNode = queue.remove();
System.out.println(curNode);
if (curNode.left!=null){
queue.add(curNode.left);
}
if (curNode.right!=null){
queue.add(curNode.right);
}
}
}
}