算法导论相关的博客类似自己的笔记,如果想学习,最好还是看看别人的吧。
最底下有新的NodeAction代码
红黑树,就是二叉树上有红色节点和黑色节点。需要满足以下几个要求:
1、每个节点要么是红的,要么是黑的。
2、根节点是黑色的。
3、每个叶子节点都是null节点,黑色的。
4、从根节点往下走,到任一叶子节点,经历的黑色数要一致。
5、红节点的子节点必须要是黑色的。
满足以上几个要求之后,就保证这个二叉树不会过长,因为4、5的要求,保证最长路径比最短路径,不会差过2倍,对于查询而言是非常好的事情,查询时间就是O(lgn)。
但是要保证红黑树的要求,还是不简单的,先说插入。
插入:
插入相对简单。
1、父亲是黑色的:直接插入,节点设为红色,不会破坏5条限制。
2、父节点是红色的:判断叔节点,如果叔节点是红色的:将叔节点和父节点染成黑子,爷节点染成红色,把叶节点当成新节点进行插入判断。
3、父节点是红色、叔节点是黑色时:就是旋转后改色,具体如下:
1)如果父节点在爷节点左,本节点在父节点左,爷节点右旋,爷节点变成父节点子节点,现在把叶节点染红,父节点染黑。
2)如果父节点在叶节点左,本节点在父节点右,将父节点左旋,而此时结构和1)一致,进行1)之后的操作。
3)同1),4)同2),只是方向变化。
插入结束:展示部分代码。
左旋:
public void leftRotate(Node node) {
Node right = node.right;
Node parnet = node.parent;
Node rightLeft = right.left;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = right;
} else {
parnet.right = right;
}
right.parent = parnet;// 对接父节点和右节点
} else {
right.parent = null;
}
if (rightLeft != null) {
rightLeft.parent = node;
}
node.right = rightLeft;// 对接右节点的左节点和本节点
node.parent = right;
right.left = node;// 换本节点和右节点的位置
}
右旋:
public void rightRotate(Node node) {
Node left = node.left;
Node parnet = node.parent;
Node leftRight = left.right;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = left;
} else {
parnet.right = left;
}
left.parent = parnet;// 对接父节点和左节点
} else {
left.parent = null;
}
if (leftRight != null) {
leftRight.parent = node;
}
node.left = leftRight;// 对接左节点的右节点和本节点
node.parent = left;
left.right = node;// 换本节点和左节点的位置
}
插入1:
if (parent.isBlack()) {
return;// 父节点是黑色,不需要改动
}
插入2:
// 叔节点为红节点时
// 父节点和叔节点变黑,爷节点变红
// 爷节点进行相同操作
parent.color = EnumColor.black.key;
parBroNode.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
addRotate(groudPNode);
插入3:
if (parBroNode.isBlack()) {
// 叔节点为黑时
if (node == parent.left) {
// 节点是左节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 爷右旋
this.rightRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
} else {
// 如果父节点是右节点
// 父右旋
this.rightRotate(parent);
// 爷左旋
this.leftRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
}
} else {
// 节点是右节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 父左旋
this.leftRotate(parent);
// 爷右旋
this.rightRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
} else {
// 如果父节点是右节点
// 爷右旋
this.leftRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
}
}
}
删除:
删除相对复杂,首先删除的必须是没有双子节点的节点,现在设定是只有左子节点,而无右子节点,如果要删除的节点不满足,要进行调换操作,找到删除节点左子节点的最右值节点,将次节点值替换到删除位置后,二叉树大小依旧满足。
1、删除节点是红色的:直接删除,把子节点给父节点做子节点,不会破坏5项规则
2、删除节点是黑色的,则要判断兄弟节点
1)兄弟节点是红色的,此时父节点必然是黑色的,更换兄弟节点和父节点的颜色,向删除节点一侧转动,此时兄弟节点是曾经兄弟节点的子节点,所以必为黑色,进入一下循环。
2)兄弟节点是黑色时,判断兄弟节点的子节点,如果左侄节点和右侄节点都为黑色,把本节点和兄弟节点染红,父节点加一层黑色,如果父节点是黑的,则要网爷节点进行判断,这里有问题,我的判断太多,可以有修改之处。
3)兄弟节点是黑色、远侄节点[如本节点为左节点,在此侄节点为兄弟节点的右节点]为黑色(近侄节点)为红色时,更换远侄节点和兄弟节点的颜色,往远离删除节点的一侧选择,此时恰好是可能4)
4)兄弟节点是黑色、远侄节点为红色时,本节点删除、更换父节点和兄弟节点颜色,远侄节点染黑。
寻找替换节点的代码:
public Node getBesideNode(Node node) {
return getBestRight(node.left);
}
public Node getBestRight(Node node) {
if (node.right.isNullNode()) {
return node;
}
return getBestRight(node.right);
}
删除1:
if (node.isRed()) {
//System.out.println("删除红节点");
// 红节点必有父节点
Node parent = node.parent;
// 以下两个不可能都满足
if (!node.left.isNullNode()) {
//System.out.println("左节点给父节点做子节点");
//System.out.println(parent.color);
node.left.parent = parent;
if (node == parent.left) {
parent.left = node.left;
} else {
parent.right = node.left;
}
}else if (!node.right.isNullNode()) {
//System.out.println("右节点给父节点做子节点");
//System.out.println(parent.color);
node.right.parent = parent;
if (node == parent.left) {
parent.left = node.right;
} else {
parent.right = node.right;
}
}else {
/*Node top = this.getTopNode(node);
if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
System.out.println("删除前就错了");
}*/
//System.out.println("删除的没有子节点");
//System.out.println(parent.color);
if (node == parent.left) {
parent.left = Node.nullNode(node, EnumColor.black.key);
} else {
parent.right = Node.nullNode(node, EnumColor.black.key);
}
}
return;
}
删除2 1):
if (broNode.isRed()) {
//System.out.println("兄弟为红时,父节点:"+parent.color);
// 兄弟节点为红色时(父节点必为黑色)
// 切换父节点和兄弟节点的肤色
parent.color = EnumColor.red.key;
broNode.color = EnumColor.black.key;
// 进行旋转
if (parent.left == node) {
this.leftRotate(parent);
} else {
this.rightRotate(parent);
}
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//this.checkNode(top);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟为红时 错了");
//}
return;
}
删除2 2):
// 当兄弟为黑色时
if (broNode.left.isBlack() && broNode.right.isBlack()) {
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟子弟都是黑色前就错了");
//}
//System.out.println("兄弟子弟都是黑色时"+broNode.color);
// 当兄弟的子女都是黑色时
node.color = EnumColor.red.key;
broNode.color = EnumColor.red.key;
this.setColorBlack(node.parent);
//top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟子弟都是黑色时就错了");
//}
removeTrue(node);
return;
}
删除2 3):
// 当当前节点是左节点,并且兄弟节点的右节点是黑色时
if (node == parent.left && broNode.right.isBlack()) {
//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是黑色时");
broNode.color = EnumColor.red.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(broNode);
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
// 当当前节点是右节点,并且兄弟节点的左节点是黑色时
if (node == parent.right && broNode.left.isBlack()) {
//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是黑色时");
broNode.color = EnumColor.red.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(broNode);
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
删除2 4):
// 当当前节点是左节点,并且兄弟节点的右节点是红色时
if (node == parent.left && broNode.right.isRed()) {
//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是红色时");
node.color = EnumColor.red.key;
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(parent);
removeTrue(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
// 当当前节点是右节点,并且兄弟节点的左节点是红色时
if (node == parent.right && broNode.left.isRed()) {
//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是红色时");
node.color = EnumColor.red.key;
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(parent);
removeTrue(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
完整代码:
测试类:
package test2019.mon01.红黑树;
import java.util.Random;
/**
* Filename: Test.java Description: Company: sendinfo.com.cn Inc.
*
* @author: guzhangyan
* @date: 2019年1月29日 上午10:10:35
*/
public class Test {
public static void main(String[] args) {
NodeAction nodeAction = new NodeAction();
Random random = new Random();
Node top = Node.newNode(EnumColor.black.key, random.nextInt(1000));
System.out.println("起始根节点:" + top.value);
for (int i = 0; i < 1000; i++) {
Node node = Node.newNode(EnumColor.red.key, random.nextInt(1000));
nodeAction.addNode(top, node);
top = nodeAction.getTopNode(top);
}
nodeAction.checkNode(top);// 校验二叉树是否成立
System.out.println("最终根节点:" + top.value + ",根节点是:" + EnumColor.getColorValue(top.color));
// 校验最长路径和最短路径是否有相差两倍
System.out.println("最短路径:" + nodeAction.getMinLength(top));
System.out.println("最长路径:" + nodeAction.getMaxLength(top));
System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
System.out.println("剩余数值:"+nodeAction.getNodeSum(top));
System.out.println("剩余数目:"+nodeAction.getNodeSumNumber(top));
int num = nodeAction.getNodeSum(top);
int number = nodeAction.getNodeSumNumber(top);
String numStr = "";
for (int j = 0; j < 3; j++) {
numStr = "";
for (int i = 0; i < 1000; i++) {
nodeAction.checkNode(top);
// System.out.println("真错了");
nodeAction.remove(top, i);
System.out.println("删除了:"+i);
top = nodeAction.getTopNode(top);
int newNumber = nodeAction.getNodeSumNumber(top);
if(number!=newNumber) {
System.out.println("扣除"+(number-newNumber)+"次");
if(number-newNumber!=1) {
System.out.println("有问题");
nodeAction.printAllLeft(top);
}
number=newNumber;
numStr += i+",";
}
int newNum = nodeAction.getNodeSum(top);
if(num!=newNum) {
System.out.println("扣除数字为:"+(num-newNum));
num=newNum;
}
if (nodeAction.getMinBlackLength(top) != nodeAction.getMaxBlackLength(top)) {
System.out.println("已经错了");
System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
return;
}
}
System.out.println("本次删除:"+numStr);
}
nodeAction.checkNode(top);// 校验二叉树是否成立
System.out.println("最终根节点:" + top.value + ",根节点是:" + EnumColor.getColorValue(top.color));
// 校验最长路径和最短路径是否有相差两倍
System.out.println("最短路径:" + nodeAction.getMinLength(top));
System.out.println("最长路径:" + nodeAction.getMaxLength(top));
System.out.println("最短黑色路径:" + nodeAction.getMinBlackLength(top));
System.out.println("最长黑色路径:" + nodeAction.getMaxBlackLength(top));
System.out.println("剩余数值:"+nodeAction.getNodeSum(top));
System.out.println("剩余数目:"+nodeAction.getNodeSumNumber(top));
System.out.println("左遍历:");
nodeAction.printAllLeft(top);
System.out.println();
System.out.println("右遍历:");
nodeAction.printAllRight(top);
}
}
Node类:
package test2019.mon01.红黑树;
/**
* Filename: Node.java Description:
*
* @author: guzhangyan
* @date: 2019年1月29日 上午9:55:46
*/
public class Node {
public Node(Node left, Node right, Node parent, int color, Integer value) {
super();
this.left = left;
this.right = right;
this.parent = parent;
this.color = color;
this.value = value;
}
public Node() {
}
public Node left;
public Node right;
public Node parent;
public int color;// 0红色1黑色
public Integer value;
public boolean isBlack() {
return color == EnumColor.black.key;
}
public static Node nullNode(Node parent, int key) {
return new Node(null, null, parent, key, null);
}
public static Node newNode(int key, int value) {
Node node = new Node(null, null, null, key, value);
node.left = nullNode(node, EnumColor.black.key);
node.right = nullNode(node, EnumColor.black.key);
return node;
}
public boolean isNullNode() {
return value == null;
}
public Node Brother() {
Node parent = this.parent;
if(parent==null) {
System.out.println("父节点不存在,所以也没有兄弟节点");
}
Node broNode = parent.left;
if(broNode == this) {
broNode = parent.right;
}
return broNode;
}
public boolean isRed() {
return !isBlack();
}
public static Node copyOf(Node node) {
return new Node(node.left,node.right,node.parent,node.color,node.value);
}
public boolean isLeftNode() {
return this == this.parent.left;
}
public void copyOfOld(Node node) {
this.left = node.left;
this.right = node.right;
this.parent = node.parent;
this.value = node.value;
this.color = node.color;
}
}
NodeAction:
package test2019.mon01.红黑树;
/**
* Filename: NodeAction.java Description:
*
* @author: guzhangyan
* @date: 2019年1月29日 上午9:57:39
*/
public class NodeAction {
public void rightRotate(Node node) {
Node left = node.left;
Node parnet = node.parent;
Node leftRight = left.right;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = left;
} else {
parnet.right = left;
}
left.parent = parnet;// 对接父节点和左节点
} else {
left.parent = null;
}
if (leftRight != null) {
leftRight.parent = node;
}
node.left = leftRight;// 对接左节点的右节点和本节点
node.parent = left;
left.right = node;// 换本节点和左节点的位置
}
public void leftRotate(Node node) {
Node right = node.right;
Node parnet = node.parent;
Node rightLeft = right.left;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = right;
} else {
parnet.right = right;
}
right.parent = parnet;// 对接父节点和右节点
} else {
right.parent = null;
}
if (rightLeft != null) {
rightLeft.parent = node;
}
node.right = rightLeft;// 对接右节点的左节点和本节点
node.parent = right;
right.left = node;// 换本节点和右节点的位置
}
public void addLeftNode(Node parent, Node node) {
parent.left = node;
node.parent = parent;
node.left = Node.nullNode(node, EnumColor.black.key);
node.right = Node.nullNode(node, EnumColor.black.key);
node.color = EnumColor.red.key;
addRotate(node);
}
public void addRightNode(Node parent, Node node) {
parent.right = node;
node.parent = parent;
node.left = Node.nullNode(node, EnumColor.black.key);
node.right = Node.nullNode(node, EnumColor.black.key);
node.color = EnumColor.red.key;
addRotate(node);
}
// 添加之后旋转
public void addRotate(Node node) {
Node parent = node.parent;
if (parent == null) {
node.color = EnumColor.black.key;
return;
}
if (parent.isBlack()) {
return;// 父节点是黑色,不需要改动
}
// 当父节点是红色时,判断叔节点的颜色
Node groudPNode = parent.parent;// 爷节点
if (groudPNode == null) {
parent.color = EnumColor.black.key;
return;// 爷节点不存在时,结束
}
Node parBroNode = groudPNode.left;
if (groudPNode.left == parent) {
parBroNode = groudPNode.right;
}
if (parBroNode.isBlack()) {
// 叔节点为黑时
if (node == parent.left) {
// 节点是左节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 爷右旋
this.rightRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
} else {
// 如果父节点是右节点
// 父右旋
this.rightRotate(parent);
// 爷左旋
this.leftRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
}
} else {
// 节点是右节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 父左旋
this.leftRotate(parent);
// 爷右旋
this.rightRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
} else {
// 如果父节点是右节点
// 爷右旋
this.leftRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
}
}
} else {
// 叔节点为红节点时
// 父节点和叔节点变黑,爷节点变红
// 爷节点进行相同操作
parent.color = EnumColor.black.key;
parBroNode.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
addRotate(groudPNode);
}
}
public void addNode(Node parent, Node node) {
if (parent.value > node.value) {
if (parent.left.isNullNode()) {
this.addLeftNode(parent, node);
} else {
addNode(parent.left, node);
}
} else {
if (parent.right.isNullNode()) {
this.addRightNode(parent, node);
} else {
addNode(parent.right, node);
}
}
}
public Node getTopNode(Node node) {
Node top = node;
while (top.parent != null) {
top = top.parent;
}
return top;
}
public int getMinLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMinLength(node.left);
int rightlength = getMinLength(node.right);
return (leftlength > rightlength ? rightlength : leftlength) + 1;
}
public int getMaxLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMaxLength(node.left);
int rightlength = getMaxLength(node.right);
return (leftlength < rightlength ? rightlength : leftlength) + 1;
}
public void checkNode(Node node) {
if (!node.left.isNullNode()) {
if (node.left.value > node.value) {
System.out.println("出错了");
return;
}
if(node.isRed()) {
if(node.left.isRed()) {
System.out.println("左双红:"+node.value+":"+node.left.value);
//System.out.println(this.getTopNode(node).value);
return;
}
}
this.checkNode(node.left);
}
if (!node.right.isNullNode()) {
if (node.right.value < node.value) {
System.out.println("出错了");
return;
}
if(node.isRed()) {
if(node.right.isRed()) {
System.out.println("右双红:"+node.value+":"+node.right.value);
//System.out.println(this.getTopNode(node).value);
return;
}
}
this.checkNode(node.right);
}
}
public int getMinBlackLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMinBlackLength(node.left);
int rightlength = getMinBlackLength(node.right);
return (leftlength > rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
}
public int getMaxBlackLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMaxBlackLength(node.left);
int rightlength = getMaxBlackLength(node.right);
return (leftlength < rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
}
public void remove(Node node, int value) {
if (node.value.equals(value)) {
remove(node);
return;
}
if (node.value - value > 0) {
if (!node.left.isNullNode()) {
remove(node.left, value);
}
} else {
if (!node.right.isNullNode()) {
remove(node.right, value);
}
}
}
public void remove(Node node) {
//System.out.println("开始删除:"+node.value);
if ((!node.left.isNullNode()) && (!node.right.isNullNode())) {
// 当节点左右节点都在时
Node besideNode = getBesideNode(node);
node.value = besideNode.value;
removeTrue(besideNode);
return;
}
removeTrue(node);
}
public Node getBesideNode(Node node) {
return getBestRight(node.left);
}
public Node getBestRight(Node node) {
if (node.right.isNullNode()) {
return node;
}
return getBestRight(node.right);
}
public void change(Node node, Node besideNode) {
Node newNode = Node.copyOf(node);
node = Node.copyOf(besideNode);
besideNode = Node.copyOf(newNode);
int value = node.value;
node.value = besideNode.value;
besideNode.value = value;
}
public void removeTrue(Node node) {
if (node.isRed()) {
//System.out.println("删除红节点");
// 红节点必有父节点
Node parent = node.parent;
// 以下两个不可能都满足
if (!node.left.isNullNode()) {
//System.out.println("左节点给父节点做子节点");
//System.out.println(parent.color);
node.left.parent = parent;
if (node == parent.left) {
parent.left = node.left;
} else {
parent.right = node.left;
}
}else if (!node.right.isNullNode()) {
//System.out.println("右节点给父节点做子节点");
//System.out.println(parent.color);
node.right.parent = parent;
if (node == parent.left) {
parent.left = node.right;
} else {
parent.right = node.right;
}
}else {
/*Node top = this.getTopNode(node);
if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
System.out.println("删除前就错了");
}*/
//System.out.println("删除的没有子节点");
//System.out.println(parent.color);
if (node == parent.left) {
parent.left = Node.nullNode(node, EnumColor.black.key);
} else {
parent.right = Node.nullNode(node, EnumColor.black.key);
}
}
return;
}
// 当节点是黑色时
// 当不存在父节点时
//System.out.println("黑色");
if (node.parent == null) {
System.out.println("我是根节点");
if (!node.left.isNullNode()) {
node.copyOfOld(node.left);
node.parent = null;
node.color = EnumColor.black.key;
return;
}
if (!node.right.isNullNode()) {
node.copyOfOld(node.right);
node.parent = null;
node.color = EnumColor.black.key;
return;
}
System.out.println("我是最后一个了,不知道怎么删除了");
return;
}
this.removeTrueBlackNode(node);
}
public void removeTrueBlackNode(Node node) {
//System.out.println("删除黑节点");
// 如果有父节点,而本节点是黑色,所以必有兄弟节点
Node parent = node.parent;
Node broNode = node.Brother();
if (broNode.isRed()) {
//System.out.println("兄弟为红时,父节点:"+parent.color);
// 兄弟节点为红色时(父节点必为黑色)
// 切换父节点和兄弟节点的肤色
parent.color = EnumColor.red.key;
broNode.color = EnumColor.black.key;
// 进行旋转
if (parent.left == node) {
this.leftRotate(parent);
} else {
this.rightRotate(parent);
}
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//this.checkNode(top);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟为红时 错了");
//}
return;
}
// 当兄弟为黑色时
if (broNode.left.isBlack() && broNode.right.isBlack()) {
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟子弟都是黑色前就错了");
//}
//System.out.println("兄弟子弟都是黑色时"+broNode.color);
// 当兄弟的子女都是黑色时
node.color = EnumColor.red.key;
broNode.color = EnumColor.red.key;
this.setColorBlack(node.parent);
//top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//System.out.println("兄弟子弟都是黑色时就错了");
//}
removeTrue(node);
return;
}
// 当兄弟的子女不都是黑色时
// 当当前节点是左节点,并且兄弟节点的右节点是黑色时
if (node == parent.left && broNode.right.isBlack()) {
//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是黑色时");
broNode.color = EnumColor.red.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(broNode);
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
// 当当前节点是右节点,并且兄弟节点的左节点是黑色时
if (node == parent.right && broNode.left.isBlack()) {
//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是黑色时");
broNode.color = EnumColor.red.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(broNode);
removeTrueBlackNode(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
// 当当前节点是左节点,并且兄弟节点的右节点是红色时
if (node == parent.left && broNode.right.isRed()) {
//System.out.println("当当前节点是左节点,并且兄弟节点的右节点是红色时");
node.color = EnumColor.red.key;
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(parent);
removeTrue(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
// 当当前节点是右节点,并且兄弟节点的左节点是红色时
if (node == parent.right && broNode.left.isRed()) {
//System.out.println("当当前节点是右节点,并且兄弟节点的左节点是红色时");
node.color = EnumColor.red.key;
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(parent);
removeTrue(node);
//Node top = this.getTopNode(node);
//if(this.getMinBlackLength(top)!=this.getMaxBlackLength(top)) {
//}
return;
}
System.out.println("怎么到这了?"+(node == parent.right)+broNode.left.isBlack()+broNode.right.isBlack());
}
public void setColorBlack(Node node) {
if(node.isRed()) {
//System.out.println("红变黑");
node.color = EnumColor.black.key;
}else {
setColorBlackTrue(node);
}
}
public void setColorBlackTrue(Node node) {
//System.out.println("开始变黑");
if(node.parent==null) {
return;
}
if(node.parent.isRed()) {
//Node top = this.getTopNode(node);
//this.checkNode(top);
//System.out.println("父节点是红的");
//System.out.println(this.getMinBlackLength(node)+":"+this.getMaxBlackLength(node));
//System.out.println(this.getMinBlackLength(node.Brother())+":"+this.getMaxBlackLength(node.Brother()));
//如果父节点是红的,则子节点必为黑色,旋转
if(node.isLeftNode()) {
if(node.Brother().left.isBlack()) {
this.leftRotate(node.parent);
}else {
if(node.Brother().right.isRed()) {
this.leftRotate(node.parent);
node.parent.color = EnumColor.black.key;
node.parent.Brother().color = EnumColor.black.key;
node.parent.parent.color = EnumColor.red.key;
}else {
Node broNode = node.Brother();
broNode.color = EnumColor.red.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(broNode);
setColorBlackTrue(node);
}
}
}else {
if(node.Brother().right.isBlack()) {
this.rightRotate(node.parent);
}else {
if(node.Brother().left.isRed()) {
this.rightRotate(node.parent);
node.parent.color = EnumColor.black.key;
node.parent.Brother().color = EnumColor.black.key;
node.parent.parent.color = EnumColor.red.key;
}else {
Node broNode = node.Brother();
broNode.color = EnumColor.red.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(broNode);
setColorBlackTrue(node);
}
}
}
//top = this.getTopNode(node);
//this.checkNode(top);
}else {
//System.out.println("父节点是黑的");
//如果父节点是黑色的,判断兄弟节点
if(node.Brother().isRed()) {
//如果兄弟节点是红色的
//System.out.println("兄弟是红的");
node.parent.color = EnumColor.red.key;
node.Brother().color = EnumColor.black.key;
if(node.isLeftNode()) {
this.leftRotate(node.parent);
}else {
this.rightRotate(node.parent);
}
setColorBlackTrue(node);
}
else {
Node broNode = node.Brother();
//System.out.println("兄弟是黑的"+":自己"+node.color);
//System.out.println(this.getMinBlackLength(node)+":"+this.getMaxBlackLength(node));
//System.out.println(this.getMinBlackLength(broNode)+":"+this.getMaxBlackLength(broNode));
if(node.isLeftNode()) {
if(broNode.left.isBlack()) {
//System.out.println("兄弟是黑的1");
node.parent.color = EnumColor.red.key;
this.leftRotate(node.parent);
setColorBlackTrue(node.parent.parent);
return;
}
if(broNode.left.isRed()&&broNode.right.isRed()) {
//System.out.println("兄弟是黑的11");
broNode.right.color = EnumColor.black.key;
this.leftRotate(node.parent);
return;
}
if(broNode.left.isRed()&&broNode.right.isBlack()) {
//System.out.println("兄弟是黑的12");
broNode.color = EnumColor.red.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(broNode);
setColorBlackTrue(node);
return;
}
}else {
if(broNode.right.isBlack()) {
//System.out.println("兄弟是黑的2");
node.parent.color = EnumColor.red.key;
this.rightRotate(node.parent);
setColorBlackTrue(node.parent.parent);
return;
}
if(broNode.right.isRed()&&broNode.left.isRed()) {
//System.out.println("兄弟是黑的21");
broNode.left.color = EnumColor.black.key;
this.rightRotate(node.parent);
return;
}
if(broNode.right.isRed()&&broNode.left.isBlack()) {
//System.out.println("兄弟是黑的22");
broNode.color = EnumColor.red.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(broNode);
setColorBlackTrue(node);
return;
}
}
}
}
}
public int getNodeSumNumber(Node node) {
int num = 1;
if(!node.left.isNullNode()) {
num += getNodeSumNumber(node.left);
}
if(!node.right.isNullNode()) {
num += getNodeSumNumber(node.right);
}
return num;
}
public int getNodeSum(Node node) {
int num = node.value;
if(!node.left.isNullNode()) {
num += getNodeSum(node.left);
}
if(!node.right.isNullNode()) {
num += getNodeSum(node.right);
}
return num;
}
public void printAllLeft(Node node) {
System.out.print(node.value+",");
if(!node.left.isNullNode()) {
printAllLeft(node.left);
}
if(!node.right.isNullNode()) {
printAllLeft(node.right);
}
}
public void printAllRight(Node node) {
System.out.print(node.value+",");
if(!node.right.isNullNode()) {
printAllRight(node.right);
}
if(!node.left.isNullNode()) {
printAllRight(node.left);
}
}
}
枚举:
package test2019.mon01.红黑树;
import java.util.HashMap;
import java.util.Map;
/**
* Filename: EnumColor.java
* Description:
* Company: sendinfo.com.cn Inc.
* @author: guzhangyan
* @date: 2019年1月29日 上午11:40:05
*/
public enum EnumColor {
black(1,"黑节点"),
red(0,"红节点");
public int key;
public String value;
EnumColor(int key,String value){
this.key = key;
this.value = value;
}
public static Map<Integer,String> map = new HashMap<>();
public static String getColorValue(int key) {
if(map.isEmpty()) {
EnumColor[] colors = EnumColor.values();
for (EnumColor color : colors) {
map.put(color.key, color.value);
}
}
return map.get(key);
}
}
新NodeAction代码
把部分功能合并
package test2019.mon01.红黑树;
/**
* Filename: NodeAction.java Description:
*
* @author: guzhangyan
* @date: 2019年1月29日 上午9:57:39
*/
public class NodeAction {
// 左旋
public void rightRotate(Node node) {
Node left = node.left;
Node parnet = node.parent;
Node leftRight = left.right;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = left;
} else {
parnet.right = left;
}
left.parent = parnet;// 对接父节点和左节点
} else {
left.parent = null;
}
if (leftRight != null) {
leftRight.parent = node;
}
node.left = leftRight;// 对接左节点的右节点和本节点
node.parent = left;
left.right = node;// 换本节点和左节点的位置
}
// 右旋
public void leftRotate(Node node) {
Node right = node.right;
Node parnet = node.parent;
Node rightLeft = right.left;
if (parnet != null) {
if (parnet.left == node) {
parnet.left = right;
} else {
parnet.right = right;
}
right.parent = parnet;// 对接父节点和右节点
} else {
right.parent = null;
}
if (rightLeft != null) {
rightLeft.parent = node;
}
node.right = rightLeft;// 对接右节点的左节点和本节点
node.parent = right;
right.left = node;// 换本节点和右节点的位置
}
// 添加左节点
public void addLeftNode(Node parent, Node node) {
parent.left = node;
node.parent = parent;
node.left = Node.nullNode(node, EnumColor.black.key);
node.right = Node.nullNode(node, EnumColor.black.key);
node.color = EnumColor.red.key;
addRotate(node);
}
// 添加右节点
public void addRightNode(Node parent, Node node) {
parent.right = node;
node.parent = parent;
node.left = Node.nullNode(node, EnumColor.black.key);
node.right = Node.nullNode(node, EnumColor.black.key);
node.color = EnumColor.red.key;
addRotate(node);
}
// 添加之后旋转
public void addRotate(Node node) {
Node parent = node.parent;
if (parent == null) {
node.color = EnumColor.black.key;
return;
}
if (parent.isBlack()) {
return;// 父节点是黑色,不需要改动
}
// 当父节点是红色时,判断叔节点的颜色
Node groudPNode = parent.parent;// 爷节点
if (groudPNode == null) {
parent.color = EnumColor.black.key;
return;// 爷节点不存在时,结束
}
Node parBroNode = groudPNode.left;
if (groudPNode.left == parent) {
parBroNode = groudPNode.right;
}
if (parBroNode.isBlack()) {
// 叔节点为黑时
if (node == parent.left) {
// 节点是左节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 爷右旋
this.rightRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
} else {
// 如果父节点是右节点
// 父右旋
this.rightRotate(parent);
// 爷左旋
this.leftRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
}
} else {
// 节点是右节点
if (groudPNode.left == parent) {
// 如果父节点是左节点
// 父左旋
this.leftRotate(parent);
// 爷右旋
this.rightRotate(groudPNode);
groudPNode.color = EnumColor.red.key;
node.color = EnumColor.black.key;
} else {
// 如果父节点是右节点
// 爷右旋
this.leftRotate(groudPNode);
parent.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
}
}
} else {
// 叔节点为红节点时
// 父节点和叔节点变黑,爷节点变红
// 爷节点进行相同操作
parent.color = EnumColor.black.key;
parBroNode.color = EnumColor.black.key;
groudPNode.color = EnumColor.red.key;
addRotate(groudPNode);
}
}
public void addNode(Node parent, Node node) {
if (parent.value > node.value) {
if (parent.left.isNullNode()) {
this.addLeftNode(parent, node);
} else {
addNode(parent.left, node);
}
} else {
if (parent.right.isNullNode()) {
this.addRightNode(parent, node);
} else {
addNode(parent.right, node);
}
}
}
// 判断要删谁
public void remove(Node node, int value) {
if (node.value.equals(value)) {
remove(node);
return;
}
if (node.value - value > 0) {
if (!node.left.isNullNode()) {
remove(node.left, value);
}
} else {
if (!node.right.isNullNode()) {
remove(node.right, value);
}
}
}
public void remove(Node node) {
if ((!node.left.isNullNode()) && (!node.right.isNullNode())) {
Node besideNode = getBesideNode(node);
node.value = besideNode.value;
removeTrue(besideNode);
return;
}
removeTrue(node);
}
// 获取要换的节点
public Node getBesideNode(Node node) {
return getBestRight(node.left);
}
public Node getBestRight(Node node) {
if (node.right.isNullNode()) {
return node;
}
return getBestRight(node.right);
}
// 删除
public void removeTrue(Node node) {
if (node.parent == null) {
System.out.println("我是根节点");
if (!node.left.isNullNode()) {
node.copyOfOld(node.left);
node.parent = null;
node.color = EnumColor.black.key;
return;
}
if (!node.right.isNullNode()) {
node.copyOfOld(node.right);
node.parent = null;
node.color = EnumColor.black.key;
return;
}
System.out.println("我是最后一个了,不知道怎么删除了");
return;
}
if (node.isBlack()) {
deleteBefore(node);
}
deleteNode(node);
}
// 删除前的校验
public void deleteBefore(Node node) {
Node parent = node.parent;
if (node.parent == null) {
return;
}
Node broNode = node.Brother();
if (broNode.isRed()) {
parent.color = EnumColor.red.key;
broNode.color = EnumColor.black.key;
if (parent.left == node) {
this.leftRotate(parent);
} else {
this.rightRotate(parent);
}
deleteBefore(node);
return;
}
if (broNode.left.isBlack() && broNode.right.isBlack()) {
broNode.color = EnumColor.red.key;
if (node.parent.isBlack()) {
deleteBefore(node.parent);
} else {
node.parent.color = EnumColor.black.key;
}
return;
}
if (node == parent.left && broNode.right.isBlack()) {
broNode.color = EnumColor.red.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(broNode);
deleteBefore(node);
return;
}
if (node == parent.right && broNode.left.isBlack()) {
broNode.color = EnumColor.red.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(broNode);
deleteBefore(node);
return;
}
if (node == parent.left && broNode.right.isRed()) {
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.right.color = EnumColor.black.key;
this.leftRotate(parent);
return;
}
if (node == parent.right && broNode.left.isRed()) {
broNode.color = node.parent.color;
node.parent.color = EnumColor.black.key;
broNode.left.color = EnumColor.black.key;
this.rightRotate(parent);
return;
}
System.out.println("怎么到这了?" + (node == parent.right) + broNode.left.isBlack() + broNode.right.isBlack());
}
// 真删除接口
public void deleteNode(Node node) {
Node parent = node.parent;
if (!node.left.isNullNode()) {
node.left.parent = parent;
if (node == parent.left) {
parent.left = node.left;
} else {
parent.right = node.left;
}
} else if (!node.right.isNullNode()) {
node.right.parent = parent;
if (node == parent.left) {
parent.left = node.right;
} else {
parent.right = node.right;
}
} else {
if (node == parent.left) {
parent.left = Node.nullNode(node, EnumColor.black.key);
} else {
parent.right = Node.nullNode(node, EnumColor.black.key);
}
}
}
/** 以下都是辅助接口 */
public Node getTopNode(Node node) {
Node top = node;
while (top.parent != null) {
top = top.parent;
}
return top;
}
public void checkNode(Node node) {
if (!node.left.isNullNode()) {
if (node.left.value > node.value) {
System.out.println("出错了");
return;
}
if (node.isRed()) {
if (node.left.isRed()) {
System.out.println("左双红:" + node.value + ":" + node.left.value);
return;
}
}
this.checkNode(node.left);
}
if (!node.right.isNullNode()) {
if (node.right.value < node.value) {
System.out.println("出错了");
return;
}
if (node.isRed()) {
if (node.right.isRed()) {
System.out.println("右双红:" + node.value + ":" + node.right.value);
return;
}
}
this.checkNode(node.right);
}
}
public int getNodeSumNumber(Node node) {
int num = 1;
if (!node.left.isNullNode()) {
num += getNodeSumNumber(node.left);
}
if (!node.right.isNullNode()) {
num += getNodeSumNumber(node.right);
}
return num;
}
public int getNodeSum(Node node) {
int num = node.value;
if (!node.left.isNullNode()) {
num += getNodeSum(node.left);
}
if (!node.right.isNullNode()) {
num += getNodeSum(node.right);
}
return num;
}
public int getMinLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMinLength(node.left);
int rightlength = getMinLength(node.right);
return (leftlength > rightlength ? rightlength : leftlength) + 1;
}
public int getMaxLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMaxLength(node.left);
int rightlength = getMaxLength(node.right);
return (leftlength < rightlength ? rightlength : leftlength) + 1;
}
public int getMinBlackLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMinBlackLength(node.left);
int rightlength = getMinBlackLength(node.right);
return (leftlength > rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
}
public int getMaxBlackLength(Node node) {
if (node.isNullNode()) {
return 0;
}
int leftlength = getMaxBlackLength(node.left);
int rightlength = getMaxBlackLength(node.right);
return (leftlength < rightlength ? rightlength : leftlength) + (node.isBlack() ? 1 : 0);
}
public void printAllLeft(Node node) {
System.out.print(node.value + ",");
if (!node.left.isNullNode()) {
printAllLeft(node.left);
}
if (!node.right.isNullNode()) {
printAllLeft(node.right);
}
}
public void printAllRight(Node node) {
System.out.print(node.value + ",");
if (!node.right.isNullNode()) {
printAllRight(node.right);
}
if (!node.left.isNullNode()) {
printAllRight(node.left);
}
}
}