红黑树特征:
节点是红色或黑色。
根节点是黑色。
每个叶子节点都是黑色的空节点(NIL节点)。
每个红色节点的两个子节点都是黑色。
从根节点到任一叶子节点的路径都包含相同数量的黑色节点。
变色旋转规则:
LR结构和RL结构要先进行旋转。
父节点是黑色,不用调整。
父节点是红色:
叔叔节点不存在,旋转当前节点的父节点与祖父节点,并将参与旋转的节点变色。
叔叔节点是红色,父节点和叔叔节点变为黑色,祖父节点变为红色。
叔叔节点是黑色,旋转当前节点的父节点与祖父节点,并将参与旋转的节点变色。
public class RedBlackTreeDemo {
private static RedBlackNode root;
public static void main(String[] args) {
RedBlackTreeDemo redBlackTreeDemo = new RedBlackTreeDemo();
redBlackTreeDemo.insert(10);
redBlackTreeDemo.insert(20);
redBlackTreeDemo.insert(30);
redBlackTreeDemo.insert(40);
redBlackTreeDemo.insert(50);
redBlackTreeDemo.insert(60);
redBlackTreeDemo.insert(70);
redBlackTreeDemo.insert(80);
redBlackTreeDemo.insert(90);
redBlackTreeDemo.insert(100);
}
public void insert(int data) {
RedBlackNode node = new RedBlackNode(data, null, null, null, Boolean.TRUE);
if (root == null) {
root = node;
setBlack(root);
} else {
// 用于与插入节点进行比较
RedBlackNode compareNode = root;
// 记录插入节点的父节点
RedBlackNode parent = null;
while (compareNode != null) {
parent = compareNode;
if (data <= compareNode.getData()) {
compareNode = compareNode.getLeft();
} else {
compareNode = compareNode.getRight();
}
}
if (parent.getData() > data) {
parent.setLeft(node);
} else {
parent.setRight(node);
}
node.setParent(parent);
adjustTree(node);
}
}
// 对节点进行变色和旋转
public void adjustTree(RedBlackNode node) {
// 当前进行校验的节点
RedBlackNode currentNode = node;
// 当前节点的父节点为红色且有父节点要循环向上校验节点
while (currentNode.getParent() != null && currentNode.getParent().isRed()) {
RedBlackNode parentNode = currentNode.getParent();
RedBlackNode grandParentNode = parentNode.getParent();
// 祖父节点为空,说明父节点就是根节点,把当前节点设置为根节点跳出循环
if (grandParentNode == null && parentNode.equals(root)) {
currentNode = parentNode;
continue;
}
// 校验当前节点的父节点位置
if (parentNode.equals(grandParentNode.getLeft())) {
RedBlackNode uncleNode = grandParentNode.getRight();
// 叔叔节点为空,以父节点为基旋转父节点和祖父节点
if (uncleNode == null) {
// 父节点和当前节点为LL结构,正常进行旋转
if (currentNode.equals(parentNode.getLeft())) {
rightRotate(parentNode);
currentNode = grandParentNode;
} else {
// 父节点和当前节点为LR结构,先进行一次以当前节点为基进行旋转,无需改变当前节点继续进行校验
parentNode.setParent(currentNode);
node.setLeft(parentNode);
}
} else if (uncleNode.isRed()) {
// 叔叔节点为红色,父节点和叔叔节点变色,祖父节点变色
changeColor(parentNode);
changeColor(uncleNode);
if (!grandParentNode.equals(root)) {
changeColor(grandParentNode);
}
currentNode = grandParentNode;
} else {
// 叔叔节点为黑色,以父节点为基旋转父节点和祖父节点
rightRotate(parentNode);
currentNode = grandParentNode;
}
} else {
RedBlackNode uncleNode = grandParentNode.getLeft();
if (uncleNode == null) {
// 父节点和当前节点为RR结构,正常进行旋转
if (currentNode.equals(parentNode.getRight())) {
leftRotate(parentNode);
currentNode = grandParentNode;
} else {
// 父节点和当前节点为LR结构,先进行一次以当前节点为基进行旋转,无需改变当前节点继续进行校验
parentNode.setParent(currentNode);
node.setRight(parentNode);
}
} else if (uncleNode.isRed()) {
// 叔叔节点为红色,父节点和叔叔节点变色,祖父节点变色
changeColor(parentNode);
changeColor(uncleNode);
if (!grandParentNode.equals(root)) {
changeColor(grandParentNode);
}
currentNode = grandParentNode;
} else {
// 叔叔节点为黑色,以父节点为基旋转父节点和祖父节点
leftRotate(parentNode);
currentNode = grandParentNode;
}
}
}
}
// 左旋
public void leftRotate(RedBlackNode node) {
RedBlackNode parentNode = node.getParent();
RedBlackNode grandParentNode = parentNode.getParent();
RedBlackNode currentLeftNode = node.getLeft();
if (grandParentNode == null) {
parentNode.setParent(node);
parentNode.setRight(node.getLeft());
node.setLeft(parentNode);
node.setParent(null);
root = node;
} else {
grandParentNode.setRight(node);
node.setParent(grandParentNode);
node.setLeft(parentNode);
parentNode.setParent(node);
parentNode.setRight(currentLeftNode);
}
// 对参与旋转的节点进行变色
changeColor(node);
changeColor(parentNode);
}
// 右旋
public void rightRotate(RedBlackNode node) {
RedBlackNode parentNode = node.getParent();
RedBlackNode grandParentNode = parentNode.getParent();
RedBlackNode currentRightNode = node.getLeft();
if (grandParentNode == null) {
parentNode.setParent(node);
node.setRight(parentNode);
node.setParent(null);
root = node;
} else {
grandParentNode.setLeft(node);
node.setParent(grandParentNode);
node.setRight(parentNode);
parentNode.setParent(node);
parentNode.setLeft(currentRightNode);
}
// 对参与旋转的节点进行变色
changeColor(node);
changeColor(parentNode);
}
// 变色
public void changeColor(RedBlackNode node) {
if (node.isRed()) {
setBlack(node);
} else {
setRed(node);
}
}
public void setBlack(RedBlackNode node) {
if (node != null) {
node.setRed(Boolean.FALSE);
}
}
public void setRed(RedBlackNode node) {
if (node != null) {
node.setRed(Boolean.TRUE);
}
}
public class RedBlackNode {
int data;
RedBlackNode parent;
RedBlackNode left;
RedBlackNode right;
boolean red;
public RedBlackNode() {
}
public RedBlackNode(int data, RedBlackNode parent, RedBlackNode left, RedBlackNode right, boolean red) {
this.data = data;
this.parent = parent;
this.left = left;
this.right = right;
this.red = red;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public RedBlackNode getParent() {
return parent;
}
public void setParent(RedBlackNode parent) {
this.parent = parent;
}
public RedBlackNode getLeft() {
return left;
}
public void setLeft(RedBlackNode left) {
this.left = left;
}
public RedBlackNode getRight() {
return right;
}
public void setRight(RedBlackNode right) {
this.right = right;
}
public boolean isRed() {
return red;
}
public void setRed(boolean red) {
this.red = red;
}
}
}